sway_core/language/ty/declaration/
enum.rs

1use crate::{
2    decl_engine::MaterializeConstGenerics,
3    engine_threading::*,
4    has_changes,
5    language::{parsed::EnumDeclaration, ty::TyDeclParsedType, CallPath, Visibility},
6    transform,
7    type_system::*,
8};
9use monomorphization::MonomorphizeHelper;
10use serde::{Deserialize, Serialize};
11use std::{
12    cmp::Ordering,
13    hash::{Hash, Hasher},
14};
15use sway_error::{
16    error::CompileError,
17    handler::{ErrorEmitted, Handler},
18};
19use sway_types::{Ident, Named, Span, Spanned};
20
21#[derive(Clone, Debug, Serialize, Deserialize)]
22pub struct TyEnumDecl {
23    pub call_path: CallPath,
24    pub type_parameters: Vec<TypeParameter>,
25    pub attributes: transform::AttributesMap,
26    pub variants: Vec<TyEnumVariant>,
27    pub span: Span,
28    pub visibility: Visibility,
29}
30
31impl TyDeclParsedType for TyEnumDecl {
32    type ParsedType = EnumDeclaration;
33}
34
35impl Named for TyEnumDecl {
36    fn name(&self) -> &Ident {
37        &self.call_path.suffix
38    }
39}
40
41impl EqWithEngines for TyEnumDecl {}
42impl PartialEqWithEngines for TyEnumDecl {
43    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
44        self.call_path == other.call_path
45            && self.type_parameters.eq(&other.type_parameters, ctx)
46            && self.variants.eq(&other.variants, ctx)
47            && self.visibility == other.visibility
48    }
49}
50
51impl HashWithEngines for TyEnumDecl {
52    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
53        let TyEnumDecl {
54            call_path,
55            type_parameters,
56            variants,
57            visibility,
58            // these fields are not hashed because they aren't relevant/a
59            // reliable source of obj v. obj distinction
60            span: _,
61            attributes: _,
62        } = self;
63        call_path.hash(state);
64        variants.hash(state, engines);
65        type_parameters.hash(state, engines);
66        visibility.hash(state);
67    }
68}
69
70impl SubstTypes for TyEnumDecl {
71    fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
72        has_changes! {
73            self.variants.subst(ctx);
74            self.type_parameters.subst(ctx);
75        }
76    }
77}
78
79impl Spanned for TyEnumDecl {
80    fn span(&self) -> Span {
81        self.span.clone()
82    }
83}
84
85impl IsConcrete for TyEnumDecl {
86    fn is_concrete(&self, engines: &Engines) -> bool {
87        self.type_parameters
88            .iter()
89            .all(|tp| tp.is_concrete(engines))
90    }
91}
92
93impl MonomorphizeHelper for TyEnumDecl {
94    fn type_parameters(&self) -> &[TypeParameter] {
95        &self.type_parameters
96    }
97
98    fn name(&self) -> &Ident {
99        &self.call_path.suffix
100    }
101
102    fn has_self_type_param(&self) -> bool {
103        false
104    }
105}
106
107impl MaterializeConstGenerics for TyEnumDecl {
108    fn materialize_const_generics(
109        &mut self,
110        _engines: &Engines,
111        _handler: &Handler,
112        _name: &str,
113        _value: &crate::language::ty::TyExpression,
114    ) -> Result<(), ErrorEmitted> {
115        Ok(())
116    }
117}
118
119impl TyEnumDecl {
120    pub(crate) fn expect_variant_from_name(
121        &self,
122        handler: &Handler,
123        variant_name: &Ident,
124    ) -> Result<&TyEnumVariant, ErrorEmitted> {
125        match self
126            .variants
127            .iter()
128            .find(|x| x.name.as_str() == variant_name.as_str())
129        {
130            Some(variant) => Ok(variant),
131            None => Err(handler.emit_err(CompileError::UnknownEnumVariant {
132                enum_name: self.call_path.suffix.clone(),
133                variant_name: variant_name.clone(),
134                span: variant_name.span(),
135            })),
136        }
137    }
138}
139
140impl Spanned for TyEnumVariant {
141    fn span(&self) -> Span {
142        self.span.clone()
143    }
144}
145
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct TyEnumVariant {
148    pub name: Ident,
149    pub type_argument: TypeArgument,
150    pub(crate) tag: usize,
151    pub span: Span,
152    pub attributes: transform::AttributesMap,
153}
154
155impl HashWithEngines for TyEnumVariant {
156    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
157        self.name.hash(state);
158        self.type_argument.hash(state, engines);
159        self.tag.hash(state);
160    }
161}
162
163impl EqWithEngines for TyEnumVariant {}
164impl PartialEqWithEngines for TyEnumVariant {
165    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
166        self.name == other.name
167            && self.type_argument.eq(&other.type_argument, ctx)
168            && self.tag == other.tag
169    }
170}
171
172impl OrdWithEngines for TyEnumVariant {
173    fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
174        let TyEnumVariant {
175            name: ln,
176            type_argument: lta,
177            tag: lt,
178            // these fields are not compared because they aren't relevant/a
179            // reliable source of obj v. obj distinction
180            span: _,
181            attributes: _,
182        } = self;
183        let TyEnumVariant {
184            name: rn,
185            type_argument: rta,
186            tag: rt,
187            // these fields are not compared because they aren't relevant/a
188            // reliable source of obj v. obj distinction
189            span: _,
190            attributes: _,
191        } = other;
192        ln.cmp(rn)
193            .then_with(|| lta.cmp(rta, ctx))
194            .then_with(|| lt.cmp(rt))
195    }
196}
197
198impl SubstTypes for TyEnumVariant {
199    fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
200        self.type_argument.subst_inner(ctx)
201    }
202}