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