Skip to main content

sway_core/language/ty/declaration/
declaration.rs

1use crate::{
2    decl_engine::*,
3    engine_threading::*,
4    language::{parsed::Declaration, ty::*, Visibility},
5    semantic_analysis::TypeCheckContext,
6    type_system::*,
7    types::*,
8};
9use serde::{Deserialize, Serialize};
10use std::{
11    fmt,
12    hash::{Hash, Hasher},
13};
14
15use sway_error::{
16    error::CompileError,
17    handler::{ErrorEmitted, Handler},
18};
19use sway_types::{BaseIdent, Ident, Named, Span, Spanned};
20
21#[derive(Clone, Debug, Serialize, Deserialize)]
22pub enum TyDecl {
23    VariableDecl(Box<TyVariableDecl>),
24    ConstantDecl(ConstantDecl),
25    ConfigurableDecl(ConfigurableDecl),
26    ConstGenericDecl(ConstGenericDecl),
27    TraitTypeDecl(TraitTypeDecl),
28    FunctionDecl(FunctionDecl),
29    TraitDecl(TraitDecl),
30    StructDecl(StructDecl),
31    EnumDecl(EnumDecl),
32    EnumVariantDecl(EnumVariantDecl),
33    ImplSelfOrTrait(ImplSelfOrTrait),
34    AbiDecl(AbiDecl),
35    // If type parameters are defined for a function, they are put in the namespace just for
36    // the body of that function.
37    GenericTypeForFunctionScope(GenericTypeForFunctionScope),
38    ErrorRecovery(Span, #[serde(skip)] ErrorEmitted),
39    StorageDecl(StorageDecl),
40    TypeAliasDecl(TypeAliasDecl),
41}
42
43/// This trait is used to associate a typed declaration node with its
44/// corresponding parsed declaration node by way of an associated type.
45/// This is used by the generic code in [`DeclEngine`] related to handling
46/// typed to parsed node maps.
47pub trait TyDeclParsedType {
48    type ParsedType;
49}
50
51#[derive(Clone, Debug, Serialize, Deserialize)]
52pub struct ConstGenericDecl {
53    pub decl_id: DeclId<TyConstGenericDecl>,
54}
55
56#[derive(Clone, Debug, Serialize, Deserialize)]
57pub struct ConstantDecl {
58    pub decl_id: DeclId<TyConstantDecl>,
59}
60
61impl ReplaceDecls for ConstantDecl {
62    fn replace_decls_inner(
63        &mut self,
64        decl_mapping: &DeclMapping,
65        handler: &Handler,
66        ctx: &mut TypeCheckContext,
67    ) -> Result<bool, ErrorEmitted> {
68        let mut decl = TyConstantDecl::clone(&*ctx.engines.de().get(&self.decl_id));
69        let has_changes = decl.replace_decls(decl_mapping, handler, ctx)?;
70        if has_changes {
71            let parsed_decl_id = ctx.engines.de().get_parsed_decl_id(&self.decl_id);
72            let new_ref = ctx.engines.de().insert(decl, parsed_decl_id.as_ref());
73            self.decl_id.replace_id(*new_ref.id());
74        }
75        Ok(has_changes)
76    }
77}
78
79#[derive(Clone, Debug, Serialize, Deserialize)]
80pub struct ConfigurableDecl {
81    pub decl_id: DeclId<TyConfigurableDecl>,
82}
83
84#[derive(Clone, Debug, Serialize, Deserialize)]
85pub struct TraitTypeDecl {
86    pub decl_id: DeclId<TyTraitType>,
87}
88
89#[derive(Clone, Debug, Serialize, Deserialize)]
90pub struct FunctionDecl {
91    pub decl_id: DeclId<TyFunctionDecl>,
92}
93
94#[derive(Clone, Debug, Serialize, Deserialize)]
95pub struct TraitDecl {
96    pub decl_id: DeclId<TyTraitDecl>,
97}
98
99#[derive(Clone, Debug, Serialize, Deserialize)]
100pub struct StructDecl {
101    pub decl_id: DeclId<TyStructDecl>,
102}
103
104#[derive(Clone, Debug, Serialize, Deserialize)]
105pub struct EnumDecl {
106    pub decl_id: DeclId<TyEnumDecl>,
107}
108
109#[derive(Clone, Debug, Serialize, Deserialize)]
110pub struct EnumVariantDecl {
111    pub enum_ref: DeclRefEnum,
112    pub variant_name: Ident,
113    pub variant_decl_span: Span,
114}
115
116#[derive(Clone, Debug, Serialize, Deserialize)]
117pub struct ImplSelfOrTrait {
118    pub decl_id: DeclId<TyImplSelfOrTrait>,
119}
120
121#[derive(Clone, Debug, Serialize, Deserialize)]
122pub struct AbiDecl {
123    pub decl_id: DeclId<TyAbiDecl>,
124}
125
126#[derive(Clone, Debug, Serialize, Deserialize)]
127pub struct GenericTypeForFunctionScope {
128    pub name: Ident,
129    pub type_id: TypeId,
130}
131
132#[derive(Clone, Debug, Serialize, Deserialize)]
133pub struct StorageDecl {
134    pub decl_id: DeclId<TyStorageDecl>,
135}
136
137#[derive(Clone, Debug, Serialize, Deserialize)]
138pub struct TypeAliasDecl {
139    pub decl_id: DeclId<TyTypeAliasDecl>,
140}
141
142impl EqWithEngines for TyDecl {}
143impl PartialEqWithEngines for TyDecl {
144    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
145        let decl_engine = ctx.engines().de();
146        let type_engine = ctx.engines().te();
147        match (self, other) {
148            (TyDecl::VariableDecl(x), TyDecl::VariableDecl(y)) => x.eq(y, ctx),
149            (
150                TyDecl::ConstantDecl(ConstantDecl { decl_id: lid, .. }),
151                TyDecl::ConstantDecl(ConstantDecl { decl_id: rid, .. }),
152            ) => decl_engine.get(lid).eq(&decl_engine.get(rid), ctx),
153            (
154                TyDecl::FunctionDecl(FunctionDecl { decl_id: lid, .. }),
155                TyDecl::FunctionDecl(FunctionDecl { decl_id: rid, .. }),
156            ) => decl_engine.get(lid).eq(&decl_engine.get(rid), ctx),
157            (
158                TyDecl::TraitDecl(TraitDecl { decl_id: lid, .. }),
159                TyDecl::TraitDecl(TraitDecl { decl_id: rid, .. }),
160            ) => decl_engine.get(lid).eq(&decl_engine.get(rid), ctx),
161            (
162                TyDecl::StructDecl(StructDecl { decl_id: lid, .. }),
163                TyDecl::StructDecl(StructDecl { decl_id: rid, .. }),
164            ) => decl_engine.get(lid).eq(&decl_engine.get(rid), ctx),
165            (
166                TyDecl::EnumDecl(EnumDecl { decl_id: lid, .. }),
167                TyDecl::EnumDecl(EnumDecl { decl_id: rid, .. }),
168            ) => decl_engine.get(lid).eq(&decl_engine.get(rid), ctx),
169            (
170                TyDecl::EnumVariantDecl(EnumVariantDecl {
171                    enum_ref: l_enum,
172                    variant_name: ln,
173                    ..
174                }),
175                TyDecl::EnumVariantDecl(EnumVariantDecl {
176                    enum_ref: r_enum,
177                    variant_name: rn,
178                    ..
179                }),
180            ) => {
181                ln == rn
182                    && decl_engine
183                        .get_enum(l_enum)
184                        .eq(&decl_engine.get_enum(r_enum), ctx)
185            }
186            (
187                TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id: lid, .. }),
188                TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id: rid, .. }),
189            ) => decl_engine.get(lid).eq(&decl_engine.get(rid), ctx),
190            (
191                TyDecl::AbiDecl(AbiDecl { decl_id: lid, .. }),
192                TyDecl::AbiDecl(AbiDecl { decl_id: rid, .. }),
193            ) => decl_engine.get(lid).eq(&decl_engine.get(rid), ctx),
194            (
195                TyDecl::StorageDecl(StorageDecl { decl_id: lid, .. }),
196                TyDecl::StorageDecl(StorageDecl { decl_id: rid, .. }),
197            ) => decl_engine.get(lid).eq(&decl_engine.get(rid), ctx),
198            (
199                TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id: lid, .. }),
200                TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id: rid, .. }),
201            ) => decl_engine.get(lid).eq(&decl_engine.get(rid), ctx),
202            (
203                TyDecl::GenericTypeForFunctionScope(GenericTypeForFunctionScope {
204                    name: xn,
205                    type_id: xti,
206                }),
207                TyDecl::GenericTypeForFunctionScope(GenericTypeForFunctionScope {
208                    name: yn,
209                    type_id: yti,
210                }),
211            ) => xn == yn && type_engine.get(*xti).eq(&type_engine.get(*yti), ctx),
212            (TyDecl::ErrorRecovery(x, _), TyDecl::ErrorRecovery(y, _)) => x == y,
213            _ => false,
214        }
215    }
216}
217
218impl HashWithEngines for TyDecl {
219    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
220        let decl_engine = engines.de();
221        let type_engine = engines.te();
222        std::mem::discriminant(self).hash(state);
223        match self {
224            TyDecl::VariableDecl(decl) => {
225                decl.hash(state, engines);
226            }
227            TyDecl::ConstantDecl(ConstantDecl { decl_id, .. }) => {
228                decl_engine.get(decl_id).hash(state, engines);
229            }
230            TyDecl::ConfigurableDecl(ConfigurableDecl { decl_id, .. }) => {
231                decl_engine.get(decl_id).hash(state, engines);
232            }
233            TyDecl::ConstGenericDecl(ConstGenericDecl { decl_id }) => {
234                decl_engine.get(decl_id).hash(state, engines);
235            }
236            TyDecl::TraitTypeDecl(TraitTypeDecl { decl_id, .. }) => {
237                decl_engine.get(decl_id).hash(state, engines);
238            }
239            TyDecl::FunctionDecl(FunctionDecl { decl_id, .. }) => {
240                decl_engine.get(decl_id).hash(state, engines);
241            }
242            TyDecl::TraitDecl(TraitDecl { decl_id, .. }) => {
243                decl_engine.get(decl_id).hash(state, engines);
244            }
245            TyDecl::StructDecl(StructDecl { decl_id, .. }) => {
246                decl_engine.get(decl_id).hash(state, engines);
247            }
248            TyDecl::EnumDecl(EnumDecl { decl_id, .. }) => {
249                decl_engine.get(decl_id).hash(state, engines);
250            }
251            TyDecl::EnumVariantDecl(EnumVariantDecl {
252                enum_ref,
253                variant_name,
254                ..
255            }) => {
256                enum_ref.hash(state, engines);
257                variant_name.hash(state);
258            }
259            TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id, .. }) => {
260                decl_engine.get(decl_id).hash(state, engines);
261            }
262            TyDecl::AbiDecl(AbiDecl { decl_id, .. }) => {
263                decl_engine.get(decl_id).hash(state, engines);
264            }
265            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id, .. }) => {
266                decl_engine.get(decl_id).hash(state, engines);
267            }
268            TyDecl::StorageDecl(StorageDecl { decl_id, .. }) => {
269                decl_engine.get(decl_id).hash(state, engines);
270            }
271            TyDecl::GenericTypeForFunctionScope(GenericTypeForFunctionScope { name, type_id }) => {
272                name.hash(state);
273                type_engine.get(*type_id).hash(state, engines);
274            }
275            TyDecl::ErrorRecovery(..) => {}
276        }
277    }
278}
279
280impl SubstTypes for TyDecl {
281    fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
282        match self {
283            TyDecl::VariableDecl(ref mut var_decl) => var_decl.subst(ctx),
284            TyDecl::FunctionDecl(FunctionDecl {
285                ref mut decl_id, ..
286            }) => decl_id.subst(ctx),
287            TyDecl::TraitDecl(TraitDecl {
288                ref mut decl_id, ..
289            }) => decl_id.subst(ctx),
290            TyDecl::StructDecl(StructDecl {
291                ref mut decl_id, ..
292            }) => decl_id.subst(ctx),
293            TyDecl::EnumDecl(EnumDecl {
294                ref mut decl_id, ..
295            }) => decl_id.subst(ctx),
296            TyDecl::EnumVariantDecl(EnumVariantDecl {
297                ref mut enum_ref, ..
298            }) => enum_ref.subst(ctx),
299            TyDecl::ImplSelfOrTrait(ImplSelfOrTrait {
300                ref mut decl_id, ..
301            }) => decl_id.subst(ctx),
302            TyDecl::TypeAliasDecl(TypeAliasDecl {
303                ref mut decl_id, ..
304            }) => decl_id.subst(ctx),
305            TyDecl::TraitTypeDecl(TraitTypeDecl {
306                ref mut decl_id, ..
307            }) => decl_id.subst(ctx),
308            TyDecl::ConstantDecl(ConstantDecl { decl_id }) => decl_id.subst(ctx),
309            // generics in an ABI is unsupported by design
310            TyDecl::AbiDecl(_)
311            | TyDecl::ConfigurableDecl(_)
312            | TyDecl::StorageDecl(_)
313            | TyDecl::GenericTypeForFunctionScope(_)
314            | TyDecl::ErrorRecovery(..) => HasChanges::No,
315            TyDecl::ConstGenericDecl(_) => HasChanges::No,
316        }
317    }
318}
319
320impl SpannedWithEngines for TyDecl {
321    fn span(&self, engines: &Engines) -> Span {
322        match self {
323            TyDecl::ConstantDecl(ConstantDecl { decl_id, .. }) => {
324                let decl = engines.de().get(decl_id);
325                decl.span.clone()
326            }
327            TyDecl::ConfigurableDecl(ConfigurableDecl { decl_id, .. }) => {
328                let decl = engines.de().get(decl_id);
329                decl.span.clone()
330            }
331            TyDecl::ConstGenericDecl(ConstGenericDecl { decl_id }) => {
332                let decl = engines.de().get(decl_id);
333                decl.span.clone()
334            }
335            TyDecl::TraitTypeDecl(TraitTypeDecl { decl_id }) => {
336                engines.de().get_type(decl_id).span.clone()
337            }
338            TyDecl::FunctionDecl(FunctionDecl { decl_id }) => {
339                engines.de().get_function(decl_id).span.clone()
340            }
341            TyDecl::TraitDecl(TraitDecl { decl_id }) => {
342                engines.de().get_trait(decl_id).span.clone()
343            }
344            TyDecl::StructDecl(StructDecl { decl_id }) => {
345                engines.de().get_struct(decl_id).span.clone()
346            }
347            TyDecl::EnumDecl(EnumDecl { decl_id }) => engines.de().get_enum(decl_id).span.clone(),
348            TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id }) => {
349                engines.de().get_impl_self_or_trait(decl_id).span.clone()
350            }
351            TyDecl::AbiDecl(AbiDecl { decl_id }) => engines.de().get_abi(decl_id).span.clone(),
352            TyDecl::VariableDecl(decl) => decl.name.span(),
353            TyDecl::StorageDecl(StorageDecl { decl_id }) => engines.de().get(decl_id).span.clone(),
354            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id }) => {
355                engines.de().get(decl_id).span.clone()
356            }
357            TyDecl::EnumVariantDecl(EnumVariantDecl {
358                variant_decl_span, ..
359            }) => variant_decl_span.clone(),
360            TyDecl::GenericTypeForFunctionScope(GenericTypeForFunctionScope { name, .. }) => {
361                name.span()
362            }
363            TyDecl::ErrorRecovery(span, _) => span.clone(),
364        }
365    }
366}
367
368impl DisplayWithEngines for TyDecl {
369    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> std::fmt::Result {
370        let type_engine = engines.te();
371        write!(
372            f,
373            "{} declaration ({})",
374            self.friendly_type_name(),
375            match self {
376                TyDecl::VariableDecl(decl) => {
377                    let TyVariableDecl {
378                        mutability,
379                        name,
380                        type_ascription,
381                        body,
382                        ..
383                    } = &**decl;
384                    let mut builder = String::new();
385                    match mutability {
386                        VariableMutability::Mutable => builder.push_str("mut"),
387                        VariableMutability::RefMutable => builder.push_str("ref mut"),
388                        VariableMutability::Immutable => {}
389                    }
390                    builder.push_str(name.as_str());
391                    builder.push_str(": ");
392                    builder.push_str(
393                        &engines
394                            .help_out(&*type_engine.get(type_ascription.type_id))
395                            .to_string(),
396                    );
397                    builder.push_str(" = ");
398                    builder.push_str(&engines.help_out(body).to_string());
399                    builder
400                }
401                TyDecl::FunctionDecl(FunctionDecl { decl_id }) => {
402                    engines.de().get(decl_id).name.as_str().into()
403                }
404                TyDecl::TraitDecl(TraitDecl { decl_id }) => {
405                    engines.de().get(decl_id).name.as_str().into()
406                }
407                TyDecl::StructDecl(StructDecl { decl_id }) => {
408                    engines.de().get(decl_id).name().as_str().into()
409                }
410                TyDecl::EnumDecl(EnumDecl { decl_id }) => {
411                    engines.de().get(decl_id).name().as_str().into()
412                }
413                TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id }) => {
414                    engines.de().get(decl_id).name().as_str().into()
415                }
416                TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id }) =>
417                    engines.de().get(decl_id).name().as_str().into(),
418                _ => String::new(),
419            }
420        )
421    }
422}
423
424impl DebugWithEngines for TyDecl {
425    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> std::fmt::Result {
426        let type_engine = engines.te();
427        write!(
428            f,
429            "{} declaration ({})",
430            self.friendly_type_name(),
431            match self {
432                TyDecl::VariableDecl(decl) => {
433                    let TyVariableDecl {
434                        mutability,
435                        name,
436                        type_ascription,
437                        body,
438                        ..
439                    } = &**decl;
440                    let mut builder = String::new();
441                    match mutability {
442                        VariableMutability::Mutable => builder.push_str("mut"),
443                        VariableMutability::RefMutable => builder.push_str("ref mut"),
444                        VariableMutability::Immutable => {}
445                    }
446                    builder.push_str(name.as_str());
447                    builder.push_str(": ");
448                    builder.push_str(
449                        &engines
450                            .help_out(&*type_engine.get(type_ascription.type_id))
451                            .to_string(),
452                    );
453                    builder.push_str(" = ");
454                    builder.push_str(&engines.help_out(body).to_string());
455                    builder
456                }
457                TyDecl::FunctionDecl(FunctionDecl { decl_id }) => {
458                    engines.de().get(decl_id).name.as_str().into()
459                }
460                TyDecl::TraitDecl(TraitDecl { decl_id }) => {
461                    engines.de().get(decl_id).name.as_str().into()
462                }
463                TyDecl::StructDecl(StructDecl { decl_id }) => {
464                    engines.de().get(decl_id).name().as_str().into()
465                }
466                TyDecl::EnumDecl(EnumDecl { decl_id }) => {
467                    engines.de().get(decl_id).name().as_str().into()
468                }
469                TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id }) => {
470                    let decl = engines.de().get(decl_id);
471                    return DebugWithEngines::fmt(&*decl, f, engines);
472                }
473                TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id }) =>
474                    engines.de().get(decl_id).name().as_str().into(),
475                _ => String::new(),
476            }
477        )
478    }
479}
480
481impl CollectTypesMetadata for TyDecl {
482    // this is only run on entry nodes, which must have all well-formed types
483    fn collect_types_metadata(
484        &self,
485        handler: &Handler,
486        ctx: &mut CollectTypesMetadataContext,
487    ) -> Result<Vec<TypeMetadata>, ErrorEmitted> {
488        let decl_engine = ctx.engines.de();
489        let metadata = match self {
490            TyDecl::VariableDecl(decl) => {
491                let mut body = decl.body.collect_types_metadata(handler, ctx)?;
492                body.append(
493                    &mut decl
494                        .type_ascription
495                        .type_id
496                        .collect_types_metadata(handler, ctx)?,
497                );
498                body
499            }
500            TyDecl::FunctionDecl(FunctionDecl { decl_id, .. }) => {
501                let decl = decl_engine.get_function(decl_id);
502                decl.collect_types_metadata(handler, ctx)?
503            }
504            TyDecl::ConstantDecl(ConstantDecl { decl_id, .. }) => {
505                let decl = decl_engine.get_constant(decl_id);
506                let TyConstantDecl { value, .. } = &*decl;
507                if let Some(value) = value {
508                    value.collect_types_metadata(handler, ctx)?
509                } else {
510                    vec![]
511                }
512            }
513            TyDecl::ConfigurableDecl(ConfigurableDecl { decl_id, .. }) => {
514                let decl = decl_engine.get_configurable(decl_id);
515                let TyConfigurableDecl { value, .. } = &*decl;
516                if let Some(value) = value {
517                    value.collect_types_metadata(handler, ctx)?
518                } else {
519                    return Ok(vec![]);
520                }
521            }
522            TyDecl::ErrorRecovery(..)
523            | TyDecl::StorageDecl(_)
524            | TyDecl::TraitDecl(_)
525            | TyDecl::StructDecl(_)
526            | TyDecl::EnumDecl(_)
527            | TyDecl::EnumVariantDecl(_)
528            | TyDecl::ImplSelfOrTrait(_)
529            | TyDecl::AbiDecl(_)
530            | TyDecl::TypeAliasDecl(_)
531            | TyDecl::TraitTypeDecl(_)
532            | TyDecl::GenericTypeForFunctionScope(_)
533            | TyDecl::ConstGenericDecl(_) => vec![],
534        };
535        Ok(metadata)
536    }
537}
538
539impl GetDeclIdent for TyDecl {
540    fn get_decl_ident(&self, engines: &Engines) -> Option<Ident> {
541        match self {
542            TyDecl::ConstantDecl(ConstantDecl { decl_id }) => {
543                Some(engines.de().get_constant(decl_id).name().clone())
544            }
545            TyDecl::ConfigurableDecl(ConfigurableDecl { decl_id }) => {
546                Some(engines.de().get_configurable(decl_id).name().clone())
547            }
548            TyDecl::ConstGenericDecl(ConstGenericDecl { decl_id }) => {
549                Some(engines.de().get_const_generic(decl_id).name().clone())
550            }
551            TyDecl::TraitTypeDecl(TraitTypeDecl { decl_id }) => {
552                Some(engines.de().get_type(decl_id).name().clone())
553            }
554            TyDecl::FunctionDecl(FunctionDecl { decl_id }) => {
555                Some(engines.de().get(decl_id).name.clone())
556            }
557            TyDecl::TraitDecl(TraitDecl { decl_id }) => {
558                Some(engines.de().get(decl_id).name.clone())
559            }
560            TyDecl::StructDecl(StructDecl { decl_id }) => {
561                Some(engines.de().get(decl_id).name().clone())
562            }
563            TyDecl::EnumDecl(EnumDecl { decl_id }) => {
564                Some(engines.de().get(decl_id).name().clone())
565            }
566            TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id }) => {
567                Some(engines.de().get(decl_id).name().clone())
568            }
569            TyDecl::AbiDecl(AbiDecl { decl_id }) => Some(engines.de().get(decl_id).name().clone()),
570            TyDecl::VariableDecl(decl) => Some(decl.name.clone()),
571            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id }) => {
572                Some(engines.de().get(decl_id).name().clone())
573            }
574            TyDecl::GenericTypeForFunctionScope(GenericTypeForFunctionScope { name, .. }) => {
575                Some(name.clone())
576            }
577            TyDecl::EnumVariantDecl(EnumVariantDecl { variant_name, .. }) => {
578                Some(variant_name.clone())
579            }
580            TyDecl::ErrorRecovery(..) => None,
581            TyDecl::StorageDecl(_) => None,
582        }
583    }
584}
585
586impl TyDecl {
587    pub(crate) fn get_parsed_decl(&self, decl_engine: &DeclEngine) -> Option<Declaration> {
588        match self {
589            TyDecl::VariableDecl(_decl) => None,
590            TyDecl::ConstantDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
591            TyDecl::ConfigurableDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
592            TyDecl::ConstGenericDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
593            TyDecl::TraitTypeDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
594            TyDecl::FunctionDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
595            TyDecl::TraitDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
596            TyDecl::StructDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
597            TyDecl::EnumDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
598            TyDecl::EnumVariantDecl(decl) => decl_engine.get_parsed_decl(decl.enum_ref.id()),
599            TyDecl::ImplSelfOrTrait(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
600            TyDecl::AbiDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
601            TyDecl::GenericTypeForFunctionScope(_data) => None,
602            TyDecl::StorageDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
603            TyDecl::TypeAliasDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
604            TyDecl::ErrorRecovery(_, _) => None,
605        }
606    }
607
608    /// Retrieves the declaration as a `DeclId<TyEnumDecl>`.
609    ///
610    /// Returns an error if `self` is not the [TyDecl][EnumDecl] variant.
611    pub(crate) fn to_enum_id(
612        &self,
613        handler: &Handler,
614        engines: &Engines,
615    ) -> Result<DeclId<TyEnumDecl>, ErrorEmitted> {
616        match self {
617            TyDecl::EnumDecl(EnumDecl { decl_id }) => Ok(*decl_id),
618            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id, .. }) => {
619                let alias_decl = engines.de().get_type_alias(decl_id);
620                let TyTypeAliasDecl { ty, span, .. } = &*alias_decl;
621                engines
622                    .te()
623                    .get(ty.type_id)
624                    .expect_enum(handler, engines, "", span)
625            }
626            // `Self` type parameter might resolve to an Enum
627            TyDecl::GenericTypeForFunctionScope(GenericTypeForFunctionScope {
628                type_id, ..
629            }) => match &*engines.te().get(*type_id) {
630                TypeInfo::Enum(r) => Ok(*r),
631                _ => Err(handler.emit_err(CompileError::DeclIsNotAnEnum {
632                    actually: self.friendly_type_name().to_string(),
633                    span: self.span(engines),
634                })),
635            },
636            TyDecl::ErrorRecovery(_, err) => Err(*err),
637            decl => Err(handler.emit_err(CompileError::DeclIsNotAnEnum {
638                actually: decl.friendly_type_name().to_string(),
639                span: decl.span(engines),
640            })),
641        }
642    }
643
644    /// Retrieves the declaration as a `DeclRef<DeclId<TyStructDecl>>`.
645    ///
646    /// Returns an error if `self` is not the [TyDecl][StructDecl] variant.
647    pub(crate) fn to_struct_decl(
648        &self,
649        handler: &Handler,
650        engines: &Engines,
651    ) -> Result<DeclId<TyStructDecl>, ErrorEmitted> {
652        match self {
653            TyDecl::StructDecl(StructDecl { decl_id }) => Ok(*decl_id),
654            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id, .. }) => {
655                let alias_decl = engines.de().get_type_alias(decl_id);
656                let TyTypeAliasDecl { ty, span, .. } = &*alias_decl;
657                engines
658                    .te()
659                    .get(ty.type_id)
660                    .expect_struct(handler, engines, span)
661            }
662            TyDecl::ErrorRecovery(_, err) => Err(*err),
663            decl => Err(handler.emit_err(CompileError::DeclIsNotAStruct {
664                actually: decl.friendly_type_name().to_string(),
665                span: decl.span(engines),
666            })),
667        }
668    }
669
670    /// Retrieves the declaration as a `DeclRef<DeclId<TyFunctionDecl>>`.
671    ///
672    /// Returns an error if `self` is not the [TyDecl][FunctionDecl] variant.
673    pub(crate) fn to_fn_ref(
674        &self,
675        handler: &Handler,
676        engines: &Engines,
677    ) -> Result<DeclRefFunction, ErrorEmitted> {
678        match self {
679            TyDecl::FunctionDecl(FunctionDecl { decl_id }) => {
680                let decl = engines.de().get(decl_id);
681                Ok(DeclRef::new(decl.name.clone(), *decl_id, decl.span.clone()))
682            }
683            TyDecl::ErrorRecovery(_, err) => Err(*err),
684            decl => Err(handler.emit_err(CompileError::DeclIsNotAFunction {
685                actually: decl.friendly_type_name().to_string(),
686                span: decl.span(engines),
687            })),
688        }
689    }
690
691    /// Retrieves the declaration as a variable declaration.
692    ///
693    /// Returns an error if `self` is not a [TyVariableDecl].
694    pub(crate) fn expect_variable(
695        &self,
696        handler: &Handler,
697        engines: &Engines,
698    ) -> Result<&TyVariableDecl, ErrorEmitted> {
699        match self {
700            TyDecl::VariableDecl(decl) => Ok(decl),
701            TyDecl::ErrorRecovery(_, err) => Err(*err),
702            decl => Err(handler.emit_err(CompileError::DeclIsNotAVariable {
703                actually: decl.friendly_type_name().to_string(),
704                span: decl.span(engines),
705            })),
706        }
707    }
708
709    /// Retrieves the declaration as a `DeclRef<DeclId<TyAbiDecl>>`.
710    ///
711    /// Returns an error if `self` is not the [TyDecl][AbiDecl] variant.
712    pub(crate) fn to_abi_ref(
713        &self,
714        handler: &Handler,
715        engines: &Engines,
716    ) -> Result<DeclRef<DeclId<TyAbiDecl>>, ErrorEmitted> {
717        match self {
718            TyDecl::AbiDecl(AbiDecl { decl_id }) => {
719                let abi_decl = engines.de().get_abi(decl_id);
720                Ok(DeclRef::new(
721                    abi_decl.name().clone(),
722                    *decl_id,
723                    abi_decl.span.clone(),
724                ))
725            }
726            TyDecl::ErrorRecovery(_, err) => Err(*err),
727            decl => Err(handler.emit_err(CompileError::DeclIsNotAnAbi {
728                actually: decl.friendly_type_name().to_string(),
729                span: decl.span(engines),
730            })),
731        }
732    }
733
734    /// Retrieves the declaration as a `DeclRef<DeclId<TyConstantDecl>>`.
735    ///
736    /// Returns an error if `self` is not the [TyDecl][ConstantDecl] variant.
737    pub(crate) fn to_const_ref(
738        &self,
739        handler: &Handler,
740        engines: &Engines,
741    ) -> Result<DeclRef<DeclId<TyConstantDecl>>, ErrorEmitted> {
742        match self {
743            TyDecl::ConstantDecl(ConstantDecl { decl_id }) => {
744                let const_decl = engines.de().get_constant(decl_id);
745                Ok(DeclRef::new(
746                    const_decl.name().clone(),
747                    *decl_id,
748                    const_decl.span.clone(),
749                ))
750            }
751            TyDecl::ErrorRecovery(_, err) => Err(*err),
752            decl => Err(handler.emit_err(CompileError::DeclIsNotAConstant {
753                actually: decl.friendly_type_name().to_string(),
754                span: decl.span(engines),
755            })),
756        }
757    }
758
759    pub fn get_name(&self, engines: &Engines) -> BaseIdent {
760        match self {
761            TyDecl::VariableDecl(ty_variable_decl) => ty_variable_decl.name.clone(),
762            TyDecl::ConstantDecl(constant_decl) => engines
763                .de()
764                .get_constant(&constant_decl.decl_id)
765                .call_path
766                .suffix
767                .clone(),
768            TyDecl::ConfigurableDecl(configurable_decl) => engines
769                .de()
770                .get_configurable(&configurable_decl.decl_id)
771                .call_path
772                .suffix
773                .clone(),
774            TyDecl::ConstGenericDecl(const_generic_decl) => engines
775                .de()
776                .get_const_generic(&const_generic_decl.decl_id)
777                .call_path
778                .suffix
779                .clone(),
780            TyDecl::TraitTypeDecl(trait_type_decl) => {
781                engines.de().get_type(&trait_type_decl.decl_id).name.clone()
782            }
783            TyDecl::FunctionDecl(function_decl) => engines
784                .de()
785                .get_function(&function_decl.decl_id)
786                .name
787                .clone(),
788            TyDecl::TraitDecl(trait_decl) => {
789                engines.de().get_trait(&trait_decl.decl_id).name.clone()
790            }
791            TyDecl::StructDecl(struct_decl) => engines
792                .de()
793                .get_struct(&struct_decl.decl_id)
794                .call_path
795                .suffix
796                .clone(),
797            TyDecl::EnumDecl(enum_decl) => engines
798                .de()
799                .get_enum(&enum_decl.decl_id)
800                .call_path
801                .suffix
802                .clone(),
803            TyDecl::EnumVariantDecl(_enum_variant_decl) => {
804                unreachable!()
805            }
806            TyDecl::ImplSelfOrTrait(impl_self_or_trait) => engines
807                .de()
808                .get_impl_self_or_trait(&impl_self_or_trait.decl_id)
809                .trait_name
810                .suffix
811                .clone(),
812            TyDecl::AbiDecl(abi_decl) => engines.de().get_abi(&abi_decl.decl_id).name.clone(),
813            TyDecl::GenericTypeForFunctionScope(_generic_type_for_function_scope) => unreachable!(),
814            TyDecl::ErrorRecovery(_span, _error_emitted) => unreachable!(),
815            TyDecl::StorageDecl(_storage_decl) => unreachable!(),
816            TyDecl::TypeAliasDecl(type_alias_decl) => engines
817                .de()
818                .get_type_alias(&type_alias_decl.decl_id)
819                .call_path
820                .suffix
821                .clone(),
822        }
823    }
824
825    /// Friendly name string used for error reporting,
826    /// which consists of the identifier for the declaration.
827    pub fn friendly_name(&self, engines: &Engines) -> String {
828        let decl_engine = engines.de();
829        let type_engine = engines.te();
830        match self {
831            TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id, .. }) => {
832                let decl = decl_engine.get_impl_self_or_trait(decl_id);
833                let implementing_for_type_id_arc = type_engine.get(decl.implementing_for.type_id);
834                let implementing_for_type_id = &*implementing_for_type_id_arc;
835                format!(
836                    "{} for {:?}",
837                    self.get_decl_ident(engines)
838                        .map_or(String::from(""), |f| f.as_str().to_string()),
839                    engines.help_out(implementing_for_type_id)
840                )
841            }
842            _ => self
843                .get_decl_ident(engines)
844                .map_or(String::from(""), |f| f.as_str().to_string()),
845        }
846    }
847
848    /// Friendly type name string used for various reportings,
849    /// which consists of the type name of the declaration AST node.
850    ///
851    /// Note that all friendly type names are lowercase.
852    /// This is also the case for acronyms like ABI.
853    /// For contexts in which acronyms need to be uppercase, like
854    /// e.g., error reporting, use `friendly_type_name_with_acronym`
855    /// instead.
856    pub fn friendly_type_name(&self) -> &'static str {
857        use TyDecl::*;
858        match self {
859            VariableDecl(_) => "variable",
860            ConstantDecl(_) => "constant",
861            ConfigurableDecl(_) => "configurable",
862            ConstGenericDecl(_) => "const generic",
863            TraitTypeDecl(_) => "type",
864            FunctionDecl(_) => "function",
865            TraitDecl(_) => "trait",
866            StructDecl(_) => "struct",
867            EnumDecl(_) => "enum",
868            EnumVariantDecl(_) => "enum variant",
869            ImplSelfOrTrait(_) => "impl trait",
870            AbiDecl(_) => "abi",
871            GenericTypeForFunctionScope(_) => "generic type parameter",
872            ErrorRecovery(_, _) => "error",
873            StorageDecl(_) => "contract storage",
874            TypeAliasDecl(_) => "type alias",
875        }
876    }
877
878    pub fn friendly_type_name_with_acronym(&self) -> &'static str {
879        match self.friendly_type_name() {
880            "abi" => "ABI",
881            friendly_name => friendly_name,
882        }
883    }
884
885    pub(crate) fn return_type(
886        &self,
887        handler: &Handler,
888        engines: &Engines,
889    ) -> Result<TypeId, ErrorEmitted> {
890        let type_engine = engines.te();
891        let decl_engine = engines.de();
892        let type_id = match self {
893            TyDecl::VariableDecl(decl) => decl.return_type,
894            TyDecl::FunctionDecl(FunctionDecl { decl_id, .. }) => {
895                let decl = decl_engine.get_function(decl_id);
896                decl.return_type.type_id
897            }
898            TyDecl::StructDecl(StructDecl { decl_id }) => {
899                type_engine.insert_struct(engines, *decl_id)
900            }
901            TyDecl::EnumDecl(EnumDecl { decl_id }) => type_engine.insert_enum(engines, *decl_id),
902            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id, .. }) => {
903                let decl = decl_engine.get_type_alias(decl_id);
904                decl.create_type_id(engines)
905            }
906            TyDecl::GenericTypeForFunctionScope(GenericTypeForFunctionScope {
907                type_id, ..
908            }) => *type_id,
909            decl => {
910                return Err(handler.emit_err(CompileError::NotAType {
911                    span: decl.span(engines),
912                    name: engines.help_out(decl).to_string(),
913                    actually_is: decl.friendly_type_name(),
914                }));
915            }
916        };
917        Ok(type_id)
918    }
919
920    pub(crate) fn visibility(&self, decl_engine: &DeclEngine) -> Visibility {
921        match self {
922            TyDecl::TraitDecl(TraitDecl { decl_id, .. }) => {
923                decl_engine.get_trait(decl_id).visibility
924            }
925            TyDecl::ConstantDecl(ConstantDecl { decl_id, .. }) => {
926                decl_engine.get_constant(decl_id).visibility
927            }
928            TyDecl::ConfigurableDecl(ConfigurableDecl { decl_id, .. }) => {
929                decl_engine.get_configurable(decl_id).visibility
930            }
931            TyDecl::ConstGenericDecl(_) => {
932                unreachable!("Const generics do not have visibility");
933            }
934            TyDecl::StructDecl(StructDecl { decl_id, .. }) => {
935                decl_engine.get_struct(decl_id).visibility
936            }
937            TyDecl::EnumDecl(EnumDecl { decl_id, .. }) => decl_engine.get_enum(decl_id).visibility,
938            TyDecl::EnumVariantDecl(EnumVariantDecl { enum_ref, .. }) => {
939                decl_engine.get_enum(enum_ref.id()).visibility
940            }
941            TyDecl::FunctionDecl(FunctionDecl { decl_id, .. }) => {
942                decl_engine.get_function(decl_id).visibility
943            }
944            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id, .. }) => {
945                decl_engine.get_type_alias(decl_id).visibility
946            }
947            TyDecl::GenericTypeForFunctionScope(_)
948            | TyDecl::ImplSelfOrTrait(_)
949            | TyDecl::StorageDecl(_)
950            | TyDecl::AbiDecl(_)
951            | TyDecl::TraitTypeDecl(_)
952            | TyDecl::ErrorRecovery(_, _) => Visibility::Public,
953            TyDecl::VariableDecl(decl) => decl.mutability.visibility(),
954        }
955    }
956}
957
958impl From<DeclRef<DeclId<TyTraitType>>> for TyDecl {
959    fn from(decl_ref: DeclRef<DeclId<TyTraitType>>) -> Self {
960        TyDecl::TraitTypeDecl(TraitTypeDecl {
961            decl_id: *decl_ref.id(),
962        })
963    }
964}
965
966impl From<DeclRef<DeclId<TyConstantDecl>>> for TyDecl {
967    fn from(decl_ref: DeclRef<DeclId<TyConstantDecl>>) -> Self {
968        TyDecl::ConstantDecl(ConstantDecl {
969            decl_id: *decl_ref.id(),
970        })
971    }
972}
973
974impl From<DeclRef<DeclId<TyConfigurableDecl>>> for TyDecl {
975    fn from(decl_ref: DeclRef<DeclId<TyConfigurableDecl>>) -> Self {
976        TyDecl::ConfigurableDecl(ConfigurableDecl {
977            decl_id: *decl_ref.id(),
978        })
979    }
980}
981
982impl From<DeclRef<DeclId<TyEnumDecl>>> for TyDecl {
983    fn from(decl_ref: DeclRef<DeclId<TyEnumDecl>>) -> Self {
984        TyDecl::EnumDecl(EnumDecl {
985            decl_id: *decl_ref.id(),
986        })
987    }
988}
989
990impl From<DeclRef<DeclId<TyFunctionDecl>>> for TyDecl {
991    fn from(decl_ref: DeclRef<DeclId<TyFunctionDecl>>) -> Self {
992        TyDecl::FunctionDecl(FunctionDecl {
993            decl_id: *decl_ref.id(),
994        })
995    }
996}
997
998impl From<DeclRef<DeclId<TyTraitDecl>>> for TyDecl {
999    fn from(decl_ref: DeclRef<DeclId<TyTraitDecl>>) -> Self {
1000        TyDecl::TraitDecl(TraitDecl {
1001            decl_id: *decl_ref.id(),
1002        })
1003    }
1004}
1005
1006impl From<DeclRef<DeclId<TyImplSelfOrTrait>>> for TyDecl {
1007    fn from(decl_ref: DeclRef<DeclId<TyImplSelfOrTrait>>) -> Self {
1008        TyDecl::ImplSelfOrTrait(ImplSelfOrTrait {
1009            decl_id: *decl_ref.id(),
1010        })
1011    }
1012}
1013
1014impl From<DeclRef<DeclId<TyStructDecl>>> for TyDecl {
1015    fn from(decl_ref: DeclRef<DeclId<TyStructDecl>>) -> Self {
1016        TyDecl::StructDecl(StructDecl {
1017            decl_id: *decl_ref.id(),
1018        })
1019    }
1020}
1021
1022impl From<DeclRef<DeclId<TyAbiDecl>>> for TyDecl {
1023    fn from(decl_ref: DeclRef<DeclId<TyAbiDecl>>) -> Self {
1024        TyDecl::AbiDecl(AbiDecl {
1025            decl_id: *decl_ref.id(),
1026        })
1027    }
1028}
1029
1030impl From<DeclRef<DeclId<TyStorageDecl>>> for TyDecl {
1031    fn from(decl_ref: DeclRef<DeclId<TyStorageDecl>>) -> Self {
1032        TyDecl::StorageDecl(StorageDecl {
1033            decl_id: *decl_ref.id(),
1034        })
1035    }
1036}
1037impl From<DeclRef<DeclId<TyTypeAliasDecl>>> for TyDecl {
1038    fn from(decl_ref: DeclRef<DeclId<TyTypeAliasDecl>>) -> Self {
1039        TyDecl::TypeAliasDecl(TypeAliasDecl {
1040            decl_id: *decl_ref.id(),
1041        })
1042    }
1043}