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