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