sway_core/language/ty/declaration/
declaration.rs

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