Skip to main content

sway_core/language/ty/declaration/
constant.rs

1use crate::{
2    decl_engine::{DeclMapping, MaterializeConstGenerics, ReplaceDecls},
3    engine_threading::*,
4    has_changes,
5    language::{parsed::ConstantDeclaration, ty::*, CallPath, Visibility},
6    semantic_analysis::TypeCheckContext,
7    transform,
8    type_system::*,
9    HasChanges,
10};
11use serde::{Deserialize, Serialize};
12use std::{
13    fmt,
14    hash::{Hash, Hasher},
15};
16use sway_error::handler::{ErrorEmitted, Handler};
17use sway_types::{Ident, Named, Span, Spanned};
18
19#[derive(Clone, Debug, Serialize, Deserialize)]
20pub struct TyConstantDecl {
21    pub call_path: CallPath,
22    pub value: Option<TyExpression>,
23    pub visibility: Visibility,
24    pub attributes: transform::Attributes,
25    pub return_type: TypeId,
26    pub type_ascription: GenericTypeArgument,
27    pub span: Span,
28}
29
30impl TyDeclParsedType for TyConstantDecl {
31    type ParsedType = ConstantDeclaration;
32}
33
34impl DebugWithEngines for TyConstantDecl {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>, _engines: &Engines) -> fmt::Result {
36        write!(f, "{}", self.call_path)
37    }
38}
39
40impl EqWithEngines for TyConstantDecl {}
41impl PartialEqWithEngines for TyConstantDecl {
42    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
43        let type_engine = ctx.engines().te();
44        self.call_path == other.call_path
45            && self.value.eq(&other.value, ctx)
46            && self.visibility == other.visibility
47            && self.type_ascription.eq(&other.type_ascription, ctx)
48            && type_engine
49                .get(self.return_type)
50                .eq(&type_engine.get(other.return_type), ctx)
51    }
52}
53
54impl HashWithEngines for TyConstantDecl {
55    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
56        let type_engine = engines.te();
57        let TyConstantDecl {
58            call_path,
59            value,
60            visibility,
61            return_type,
62            type_ascription,
63            // these fields are not hashed because they aren't relevant/a
64            // reliable source of obj v. obj distinction
65            attributes: _,
66            span: _,
67        } = self;
68        call_path.hash(state);
69        value.hash(state, engines);
70        visibility.hash(state);
71        type_engine.get(*return_type).hash(state, engines);
72        type_ascription.hash(state, engines);
73    }
74}
75
76impl Named for TyConstantDecl {
77    fn name(&self) -> &Ident {
78        &self.call_path.suffix
79    }
80}
81
82impl Spanned for TyConstantDecl {
83    fn span(&self) -> Span {
84        self.span.clone()
85    }
86}
87
88impl IsConcrete for TyConstantDecl {
89    fn is_concrete(&self, _: &Handler, engines: &Engines) -> bool {
90        self.return_type
91            .is_concrete(engines, TreatNumericAs::Concrete)
92    }
93}
94
95impl SubstTypes for TyConstantDecl {
96    fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
97        has_changes! {
98            self.return_type.subst(ctx);
99            self.type_ascription.subst(ctx);
100            self.value.subst(ctx);
101        }
102    }
103}
104
105impl ReplaceDecls for TyConstantDecl {
106    fn replace_decls_inner(
107        &mut self,
108        decl_mapping: &DeclMapping,
109        handler: &Handler,
110        ctx: &mut TypeCheckContext,
111    ) -> Result<HasChanges, ErrorEmitted> {
112        if let Some(expr) = &mut self.value {
113            expr.replace_decls(decl_mapping, handler, ctx)
114        } else {
115            Ok(HasChanges::No)
116        }
117    }
118}
119
120impl MaterializeConstGenerics for TyConstantDecl {
121    fn materialize_const_generics(
122        &mut self,
123        engines: &Engines,
124        handler: &Handler,
125        name: &str,
126        value: &TyExpression,
127    ) -> Result<HasChanges, ErrorEmitted> {
128        let mut has_changes = HasChanges::No;
129        if let Some(v) = self.value.as_mut() {
130            has_changes |= v.materialize_const_generics(engines, handler, name, value)?;
131        }
132        has_changes |= self
133            .return_type
134            .materialize_const_generics(engines, handler, name, value)?;
135        has_changes |= self
136            .type_ascription
137            .type_id
138            .materialize_const_generics(engines, handler, name, value)?;
139        Ok(has_changes)
140    }
141}