Skip to main content

sway_core/language/ty/declaration/
const_generic.rs

1use crate::{
2    decl_engine::MaterializeConstGenerics,
3    engine_threading::HashWithEngines,
4    has_changes,
5    language::{parsed::ConstGenericDeclaration, ty::TyExpression, CallPath},
6    semantic_analysis::{TypeCheckAnalysis, TypeCheckAnalysisContext},
7    Engines, HasChanges, SubstTypes, TypeId,
8};
9use serde::{Deserialize, Serialize};
10use std::hash::{Hash as _, Hasher};
11use sway_error::handler::{ErrorEmitted, Handler};
12use sway_types::{Ident, Named, Span, Spanned};
13
14use super::TyDeclParsedType;
15
16#[derive(Clone, Debug, Serialize, Deserialize)]
17pub struct TyConstGenericDecl {
18    pub call_path: CallPath,
19    pub return_type: TypeId,
20    pub span: Span,
21    pub value: Option<TyExpression>,
22}
23
24impl HashWithEngines for TyConstGenericDecl {
25    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
26        let type_engine = engines.te();
27        let TyConstGenericDecl {
28            call_path,
29            return_type,
30            span: _,
31            value: _,
32        } = self;
33        call_path.hash(state);
34        type_engine.get(*return_type).hash(state, engines);
35    }
36}
37
38impl SubstTypes for TyConstGenericDecl {
39    fn subst_inner(&mut self, ctx: &crate::SubstTypesContext) -> crate::HasChanges {
40        has_changes! {
41            self.return_type.subst(ctx);
42            if let Some(v) = ctx.get_renamed_const_generic(&self.call_path.suffix) {
43                self.call_path.suffix = v.clone();
44                HasChanges::Yes
45            } else {
46                HasChanges::No
47            };
48        }
49    }
50}
51
52impl MaterializeConstGenerics for TyConstGenericDecl {
53    fn materialize_const_generics(
54        &mut self,
55        _engines: &crate::Engines,
56        _handler: &Handler,
57        name: &str,
58        value: &TyExpression,
59    ) -> Result<HasChanges, ErrorEmitted> {
60        let mut has_changes = HasChanges::No;
61        if self.call_path.suffix.as_str() == name {
62            match self.value.as_ref() {
63                // If the const generic already has value,
64                // it must be the same as the `value`.
65                Some(v) => {
66                    assert!(
67                        v.extract_literal_value()
68                            .unwrap()
69                            .cast_value_to_u64()
70                            .unwrap()
71                            == value
72                                .extract_literal_value()
73                                .unwrap()
74                                .cast_value_to_u64()
75                                .unwrap(),
76                        "{v:?} {value:?}",
77                    );
78                }
79                None => {
80                    self.value = Some(value.clone());
81                    has_changes = HasChanges::Yes;
82                }
83            }
84        }
85        Ok(has_changes)
86    }
87}
88
89impl TypeCheckAnalysis for TyConstGenericDecl {
90    fn type_check_analyze(
91        &self,
92        _handler: &Handler,
93        _ctx: &mut TypeCheckAnalysisContext,
94    ) -> Result<(), ErrorEmitted> {
95        Ok(())
96    }
97}
98
99impl Named for TyConstGenericDecl {
100    fn name(&self) -> &Ident {
101        &self.call_path.suffix
102    }
103}
104
105impl Spanned for TyConstGenericDecl {
106    fn span(&self) -> Span {
107        self.span.clone()
108    }
109}
110
111impl TyDeclParsedType for TyConstGenericDecl {
112    type ParsedType = ConstGenericDeclaration;
113}