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(ConstGenericDecl { decl_id }) => {
215                decl_engine.get(decl_id).hash(state, engines);
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            TyDecl::ConstantDecl(ConstantDecl { decl_id }) => decl_id.subst(ctx),
290            // generics in an ABI is unsupported by design
291            TyDecl::AbiDecl(_)
292            | TyDecl::ConfigurableDecl(_)
293            | TyDecl::StorageDecl(_)
294            | TyDecl::GenericTypeForFunctionScope(_)
295            | TyDecl::ErrorRecovery(..) => HasChanges::No,
296            TyDecl::ConstGenericDecl(_) => HasChanges::No,
297        }
298    }
299}
300
301impl SpannedWithEngines for TyDecl {
302    fn span(&self, engines: &Engines) -> Span {
303        match self {
304            TyDecl::ConstantDecl(ConstantDecl { decl_id, .. }) => {
305                let decl = engines.de().get(decl_id);
306                decl.span.clone()
307            }
308            TyDecl::ConfigurableDecl(ConfigurableDecl { decl_id, .. }) => {
309                let decl = engines.de().get(decl_id);
310                decl.span.clone()
311            }
312            TyDecl::ConstGenericDecl(ConstGenericDecl { decl_id }) => {
313                let decl = engines.de().get(decl_id);
314                decl.span.clone()
315            }
316            TyDecl::TraitTypeDecl(TraitTypeDecl { decl_id }) => {
317                engines.de().get_type(decl_id).span.clone()
318            }
319            TyDecl::FunctionDecl(FunctionDecl { decl_id }) => {
320                engines.de().get_function(decl_id).span.clone()
321            }
322            TyDecl::TraitDecl(TraitDecl { decl_id }) => {
323                engines.de().get_trait(decl_id).span.clone()
324            }
325            TyDecl::StructDecl(StructDecl { decl_id }) => {
326                engines.de().get_struct(decl_id).span.clone()
327            }
328            TyDecl::EnumDecl(EnumDecl { decl_id }) => engines.de().get_enum(decl_id).span.clone(),
329            TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id }) => {
330                engines.de().get_impl_self_or_trait(decl_id).span.clone()
331            }
332            TyDecl::AbiDecl(AbiDecl { decl_id }) => engines.de().get_abi(decl_id).span.clone(),
333            TyDecl::VariableDecl(decl) => decl.name.span(),
334            TyDecl::StorageDecl(StorageDecl { decl_id }) => engines.de().get(decl_id).span.clone(),
335            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id }) => {
336                engines.de().get(decl_id).span.clone()
337            }
338            TyDecl::EnumVariantDecl(EnumVariantDecl {
339                variant_decl_span, ..
340            }) => variant_decl_span.clone(),
341            TyDecl::GenericTypeForFunctionScope(GenericTypeForFunctionScope { name, .. }) => {
342                name.span()
343            }
344            TyDecl::ErrorRecovery(span, _) => span.clone(),
345        }
346    }
347}
348
349impl DisplayWithEngines for TyDecl {
350    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> std::fmt::Result {
351        let type_engine = engines.te();
352        write!(
353            f,
354            "{} declaration ({})",
355            self.friendly_type_name(),
356            match self {
357                TyDecl::VariableDecl(decl) => {
358                    let TyVariableDecl {
359                        mutability,
360                        name,
361                        type_ascription,
362                        body,
363                        ..
364                    } = &**decl;
365                    let mut builder = String::new();
366                    match mutability {
367                        VariableMutability::Mutable => builder.push_str("mut"),
368                        VariableMutability::RefMutable => builder.push_str("ref mut"),
369                        VariableMutability::Immutable => {}
370                    }
371                    builder.push_str(name.as_str());
372                    builder.push_str(": ");
373                    builder.push_str(
374                        &engines
375                            .help_out(&*type_engine.get(type_ascription.type_id))
376                            .to_string(),
377                    );
378                    builder.push_str(" = ");
379                    builder.push_str(&engines.help_out(body).to_string());
380                    builder
381                }
382                TyDecl::FunctionDecl(FunctionDecl { decl_id }) => {
383                    engines.de().get(decl_id).name.as_str().into()
384                }
385                TyDecl::TraitDecl(TraitDecl { decl_id }) => {
386                    engines.de().get(decl_id).name.as_str().into()
387                }
388                TyDecl::StructDecl(StructDecl { decl_id }) => {
389                    engines.de().get(decl_id).name().as_str().into()
390                }
391                TyDecl::EnumDecl(EnumDecl { decl_id }) => {
392                    engines.de().get(decl_id).name().as_str().into()
393                }
394                TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id }) => {
395                    engines.de().get(decl_id).name().as_str().into()
396                }
397                TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id }) =>
398                    engines.de().get(decl_id).name().as_str().into(),
399                _ => String::new(),
400            }
401        )
402    }
403}
404
405impl DebugWithEngines for TyDecl {
406    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> std::fmt::Result {
407        let type_engine = engines.te();
408        write!(
409            f,
410            "{} declaration ({})",
411            self.friendly_type_name(),
412            match self {
413                TyDecl::VariableDecl(decl) => {
414                    let TyVariableDecl {
415                        mutability,
416                        name,
417                        type_ascription,
418                        body,
419                        ..
420                    } = &**decl;
421                    let mut builder = String::new();
422                    match mutability {
423                        VariableMutability::Mutable => builder.push_str("mut"),
424                        VariableMutability::RefMutable => builder.push_str("ref mut"),
425                        VariableMutability::Immutable => {}
426                    }
427                    builder.push_str(name.as_str());
428                    builder.push_str(": ");
429                    builder.push_str(
430                        &engines
431                            .help_out(&*type_engine.get(type_ascription.type_id))
432                            .to_string(),
433                    );
434                    builder.push_str(" = ");
435                    builder.push_str(&engines.help_out(body).to_string());
436                    builder
437                }
438                TyDecl::FunctionDecl(FunctionDecl { decl_id }) => {
439                    engines.de().get(decl_id).name.as_str().into()
440                }
441                TyDecl::TraitDecl(TraitDecl { decl_id }) => {
442                    engines.de().get(decl_id).name.as_str().into()
443                }
444                TyDecl::StructDecl(StructDecl { decl_id }) => {
445                    engines.de().get(decl_id).name().as_str().into()
446                }
447                TyDecl::EnumDecl(EnumDecl { decl_id }) => {
448                    engines.de().get(decl_id).name().as_str().into()
449                }
450                TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id }) => {
451                    let decl = engines.de().get(decl_id);
452                    return DebugWithEngines::fmt(&*decl, f, engines);
453                }
454                TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id }) =>
455                    engines.de().get(decl_id).name().as_str().into(),
456                _ => String::new(),
457            }
458        )
459    }
460}
461
462impl CollectTypesMetadata for TyDecl {
463    // this is only run on entry nodes, which must have all well-formed types
464    fn collect_types_metadata(
465        &self,
466        handler: &Handler,
467        ctx: &mut CollectTypesMetadataContext,
468    ) -> Result<Vec<TypeMetadata>, ErrorEmitted> {
469        let decl_engine = ctx.engines.de();
470        let metadata = match self {
471            TyDecl::VariableDecl(decl) => {
472                let mut body = decl.body.collect_types_metadata(handler, ctx)?;
473                body.append(
474                    &mut decl
475                        .type_ascription
476                        .type_id
477                        .collect_types_metadata(handler, ctx)?,
478                );
479                body
480            }
481            TyDecl::FunctionDecl(FunctionDecl { decl_id, .. }) => {
482                let decl = decl_engine.get_function(decl_id);
483                decl.collect_types_metadata(handler, ctx)?
484            }
485            TyDecl::ConstantDecl(ConstantDecl { decl_id, .. }) => {
486                let decl = decl_engine.get_constant(decl_id);
487                let TyConstantDecl { value, .. } = &*decl;
488                if let Some(value) = value {
489                    value.collect_types_metadata(handler, ctx)?
490                } else {
491                    vec![]
492                }
493            }
494            TyDecl::ConfigurableDecl(ConfigurableDecl { decl_id, .. }) => {
495                let decl = decl_engine.get_configurable(decl_id);
496                let TyConfigurableDecl { value, .. } = &*decl;
497                if let Some(value) = value {
498                    value.collect_types_metadata(handler, ctx)?
499                } else {
500                    return Ok(vec![]);
501                }
502            }
503            TyDecl::ErrorRecovery(..)
504            | TyDecl::StorageDecl(_)
505            | TyDecl::TraitDecl(_)
506            | TyDecl::StructDecl(_)
507            | TyDecl::EnumDecl(_)
508            | TyDecl::EnumVariantDecl(_)
509            | TyDecl::ImplSelfOrTrait(_)
510            | TyDecl::AbiDecl(_)
511            | TyDecl::TypeAliasDecl(_)
512            | TyDecl::TraitTypeDecl(_)
513            | TyDecl::GenericTypeForFunctionScope(_)
514            | TyDecl::ConstGenericDecl(_) => vec![],
515        };
516        Ok(metadata)
517    }
518}
519
520impl GetDeclIdent for TyDecl {
521    fn get_decl_ident(&self, engines: &Engines) -> Option<Ident> {
522        match self {
523            TyDecl::ConstantDecl(ConstantDecl { decl_id }) => {
524                Some(engines.de().get_constant(decl_id).name().clone())
525            }
526            TyDecl::ConfigurableDecl(ConfigurableDecl { decl_id }) => {
527                Some(engines.de().get_configurable(decl_id).name().clone())
528            }
529            TyDecl::ConstGenericDecl(ConstGenericDecl { decl_id }) => {
530                Some(engines.de().get_const_generic(decl_id).name().clone())
531            }
532            TyDecl::TraitTypeDecl(TraitTypeDecl { decl_id }) => {
533                Some(engines.de().get_type(decl_id).name().clone())
534            }
535            TyDecl::FunctionDecl(FunctionDecl { decl_id }) => {
536                Some(engines.de().get(decl_id).name.clone())
537            }
538            TyDecl::TraitDecl(TraitDecl { decl_id }) => {
539                Some(engines.de().get(decl_id).name.clone())
540            }
541            TyDecl::StructDecl(StructDecl { decl_id }) => {
542                Some(engines.de().get(decl_id).name().clone())
543            }
544            TyDecl::EnumDecl(EnumDecl { decl_id }) => {
545                Some(engines.de().get(decl_id).name().clone())
546            }
547            TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id }) => {
548                Some(engines.de().get(decl_id).name().clone())
549            }
550            TyDecl::AbiDecl(AbiDecl { decl_id }) => Some(engines.de().get(decl_id).name().clone()),
551            TyDecl::VariableDecl(decl) => Some(decl.name.clone()),
552            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id }) => {
553                Some(engines.de().get(decl_id).name().clone())
554            }
555            TyDecl::GenericTypeForFunctionScope(GenericTypeForFunctionScope { name, .. }) => {
556                Some(name.clone())
557            }
558            TyDecl::EnumVariantDecl(EnumVariantDecl { variant_name, .. }) => {
559                Some(variant_name.clone())
560            }
561            TyDecl::ErrorRecovery(..) => None,
562            TyDecl::StorageDecl(_) => None,
563        }
564    }
565}
566
567impl TyDecl {
568    pub(crate) fn get_parsed_decl(&self, decl_engine: &DeclEngine) -> Option<Declaration> {
569        match self {
570            TyDecl::VariableDecl(_decl) => None,
571            TyDecl::ConstantDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
572            TyDecl::ConfigurableDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
573            TyDecl::ConstGenericDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
574            TyDecl::TraitTypeDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
575            TyDecl::FunctionDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
576            TyDecl::TraitDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
577            TyDecl::StructDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
578            TyDecl::EnumDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
579            TyDecl::EnumVariantDecl(decl) => decl_engine.get_parsed_decl(decl.enum_ref.id()),
580            TyDecl::ImplSelfOrTrait(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
581            TyDecl::AbiDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
582            TyDecl::GenericTypeForFunctionScope(_data) => None,
583            TyDecl::StorageDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
584            TyDecl::TypeAliasDecl(decl) => decl_engine.get_parsed_decl(&decl.decl_id),
585            TyDecl::ErrorRecovery(_, _) => None,
586        }
587    }
588
589    /// Retrieves the declaration as a `DeclId<TyEnumDecl>`.
590    ///
591    /// Returns an error if `self` is not the [TyDecl][EnumDecl] variant.
592    pub(crate) fn to_enum_id(
593        &self,
594        handler: &Handler,
595        engines: &Engines,
596    ) -> Result<DeclId<TyEnumDecl>, ErrorEmitted> {
597        match self {
598            TyDecl::EnumDecl(EnumDecl { decl_id }) => Ok(*decl_id),
599            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id, .. }) => {
600                let alias_decl = engines.de().get_type_alias(decl_id);
601                let TyTypeAliasDecl { ty, span, .. } = &*alias_decl;
602                engines
603                    .te()
604                    .get(ty.type_id)
605                    .expect_enum(handler, engines, "", span)
606            }
607            // `Self` type parameter might resolve to an Enum
608            TyDecl::GenericTypeForFunctionScope(GenericTypeForFunctionScope {
609                type_id, ..
610            }) => match &*engines.te().get(*type_id) {
611                TypeInfo::Enum(r) => Ok(*r),
612                _ => Err(handler.emit_err(CompileError::DeclIsNotAnEnum {
613                    actually: self.friendly_type_name().to_string(),
614                    span: self.span(engines),
615                })),
616            },
617            TyDecl::ErrorRecovery(_, err) => Err(*err),
618            decl => Err(handler.emit_err(CompileError::DeclIsNotAnEnum {
619                actually: decl.friendly_type_name().to_string(),
620                span: decl.span(engines),
621            })),
622        }
623    }
624
625    /// Retrieves the declaration as a `DeclRef<DeclId<TyStructDecl>>`.
626    ///
627    /// Returns an error if `self` is not the [TyDecl][StructDecl] variant.
628    pub(crate) fn to_struct_decl(
629        &self,
630        handler: &Handler,
631        engines: &Engines,
632    ) -> Result<DeclId<TyStructDecl>, ErrorEmitted> {
633        match self {
634            TyDecl::StructDecl(StructDecl { decl_id }) => Ok(*decl_id),
635            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id, .. }) => {
636                let alias_decl = engines.de().get_type_alias(decl_id);
637                let TyTypeAliasDecl { ty, span, .. } = &*alias_decl;
638                engines
639                    .te()
640                    .get(ty.type_id)
641                    .expect_struct(handler, engines, span)
642            }
643            TyDecl::ErrorRecovery(_, err) => Err(*err),
644            decl => Err(handler.emit_err(CompileError::DeclIsNotAStruct {
645                actually: decl.friendly_type_name().to_string(),
646                span: decl.span(engines),
647            })),
648        }
649    }
650
651    /// Retrieves the declaration as a `DeclRef<DeclId<TyFunctionDecl>>`.
652    ///
653    /// Returns an error if `self` is not the [TyDecl][FunctionDecl] variant.
654    pub(crate) fn to_fn_ref(
655        &self,
656        handler: &Handler,
657        engines: &Engines,
658    ) -> Result<DeclRefFunction, ErrorEmitted> {
659        match self {
660            TyDecl::FunctionDecl(FunctionDecl { decl_id }) => {
661                let decl = engines.de().get(decl_id);
662                Ok(DeclRef::new(decl.name.clone(), *decl_id, decl.span.clone()))
663            }
664            TyDecl::ErrorRecovery(_, err) => Err(*err),
665            decl => Err(handler.emit_err(CompileError::DeclIsNotAFunction {
666                actually: decl.friendly_type_name().to_string(),
667                span: decl.span(engines),
668            })),
669        }
670    }
671
672    /// Retrieves the declaration as a variable declaration.
673    ///
674    /// Returns an error if `self` is not a [TyVariableDecl].
675    pub(crate) fn expect_variable(
676        &self,
677        handler: &Handler,
678        engines: &Engines,
679    ) -> Result<&TyVariableDecl, ErrorEmitted> {
680        match self {
681            TyDecl::VariableDecl(decl) => Ok(decl),
682            TyDecl::ErrorRecovery(_, err) => Err(*err),
683            decl => Err(handler.emit_err(CompileError::DeclIsNotAVariable {
684                actually: decl.friendly_type_name().to_string(),
685                span: decl.span(engines),
686            })),
687        }
688    }
689
690    /// Retrieves the declaration as a `DeclRef<DeclId<TyAbiDecl>>`.
691    ///
692    /// Returns an error if `self` is not the [TyDecl][AbiDecl] variant.
693    pub(crate) fn to_abi_ref(
694        &self,
695        handler: &Handler,
696        engines: &Engines,
697    ) -> Result<DeclRef<DeclId<TyAbiDecl>>, ErrorEmitted> {
698        match self {
699            TyDecl::AbiDecl(AbiDecl { decl_id }) => {
700                let abi_decl = engines.de().get_abi(decl_id);
701                Ok(DeclRef::new(
702                    abi_decl.name().clone(),
703                    *decl_id,
704                    abi_decl.span.clone(),
705                ))
706            }
707            TyDecl::ErrorRecovery(_, err) => Err(*err),
708            decl => Err(handler.emit_err(CompileError::DeclIsNotAnAbi {
709                actually: decl.friendly_type_name().to_string(),
710                span: decl.span(engines),
711            })),
712        }
713    }
714
715    /// Retrieves the declaration as a `DeclRef<DeclId<TyConstantDecl>>`.
716    ///
717    /// Returns an error if `self` is not the [TyDecl][ConstantDecl] variant.
718    pub(crate) fn to_const_ref(
719        &self,
720        handler: &Handler,
721        engines: &Engines,
722    ) -> Result<DeclRef<DeclId<TyConstantDecl>>, ErrorEmitted> {
723        match self {
724            TyDecl::ConstantDecl(ConstantDecl { decl_id }) => {
725                let const_decl = engines.de().get_constant(decl_id);
726                Ok(DeclRef::new(
727                    const_decl.name().clone(),
728                    *decl_id,
729                    const_decl.span.clone(),
730                ))
731            }
732            TyDecl::ErrorRecovery(_, err) => Err(*err),
733            decl => Err(handler.emit_err(CompileError::DeclIsNotAConstant {
734                actually: decl.friendly_type_name().to_string(),
735                span: decl.span(engines),
736            })),
737        }
738    }
739
740    pub fn get_name(&self, engines: &Engines) -> BaseIdent {
741        match self {
742            TyDecl::VariableDecl(ty_variable_decl) => ty_variable_decl.name.clone(),
743            TyDecl::ConstantDecl(constant_decl) => engines
744                .de()
745                .get_constant(&constant_decl.decl_id)
746                .call_path
747                .suffix
748                .clone(),
749            TyDecl::ConfigurableDecl(configurable_decl) => engines
750                .de()
751                .get_configurable(&configurable_decl.decl_id)
752                .call_path
753                .suffix
754                .clone(),
755            TyDecl::ConstGenericDecl(const_generic_decl) => engines
756                .de()
757                .get_const_generic(&const_generic_decl.decl_id)
758                .call_path
759                .suffix
760                .clone(),
761            TyDecl::TraitTypeDecl(trait_type_decl) => {
762                engines.de().get_type(&trait_type_decl.decl_id).name.clone()
763            }
764            TyDecl::FunctionDecl(function_decl) => engines
765                .de()
766                .get_function(&function_decl.decl_id)
767                .name
768                .clone(),
769            TyDecl::TraitDecl(trait_decl) => {
770                engines.de().get_trait(&trait_decl.decl_id).name.clone()
771            }
772            TyDecl::StructDecl(struct_decl) => engines
773                .de()
774                .get_struct(&struct_decl.decl_id)
775                .call_path
776                .suffix
777                .clone(),
778            TyDecl::EnumDecl(enum_decl) => engines
779                .de()
780                .get_enum(&enum_decl.decl_id)
781                .call_path
782                .suffix
783                .clone(),
784            TyDecl::EnumVariantDecl(_enum_variant_decl) => {
785                unreachable!()
786            }
787            TyDecl::ImplSelfOrTrait(impl_self_or_trait) => engines
788                .de()
789                .get_impl_self_or_trait(&impl_self_or_trait.decl_id)
790                .trait_name
791                .suffix
792                .clone(),
793            TyDecl::AbiDecl(abi_decl) => engines.de().get_abi(&abi_decl.decl_id).name.clone(),
794            TyDecl::GenericTypeForFunctionScope(_generic_type_for_function_scope) => unreachable!(),
795            TyDecl::ErrorRecovery(_span, _error_emitted) => unreachable!(),
796            TyDecl::StorageDecl(_storage_decl) => unreachable!(),
797            TyDecl::TypeAliasDecl(type_alias_decl) => engines
798                .de()
799                .get_type_alias(&type_alias_decl.decl_id)
800                .call_path
801                .suffix
802                .clone(),
803        }
804    }
805
806    /// Friendly name string used for error reporting,
807    /// which consists of the identifier for the declaration.
808    pub fn friendly_name(&self, engines: &Engines) -> String {
809        let decl_engine = engines.de();
810        let type_engine = engines.te();
811        match self {
812            TyDecl::ImplSelfOrTrait(ImplSelfOrTrait { decl_id, .. }) => {
813                let decl = decl_engine.get_impl_self_or_trait(decl_id);
814                let implementing_for_type_id_arc = type_engine.get(decl.implementing_for.type_id);
815                let implementing_for_type_id = &*implementing_for_type_id_arc;
816                format!(
817                    "{} for {:?}",
818                    self.get_decl_ident(engines)
819                        .map_or(String::from(""), |f| f.as_str().to_string()),
820                    engines.help_out(implementing_for_type_id)
821                )
822            }
823            _ => self
824                .get_decl_ident(engines)
825                .map_or(String::from(""), |f| f.as_str().to_string()),
826        }
827    }
828
829    /// Friendly type name string used for various reportings,
830    /// which consists of the type name of the declaration AST node.
831    ///
832    /// Note that all friendly type names are lowercase.
833    /// This is also the case for acronyms like ABI.
834    /// For contexts in which acronyms need to be uppercase, like
835    /// e.g., error reporting, use `friendly_type_name_with_acronym`
836    /// instead.
837    pub fn friendly_type_name(&self) -> &'static str {
838        use TyDecl::*;
839        match self {
840            VariableDecl(_) => "variable",
841            ConstantDecl(_) => "constant",
842            ConfigurableDecl(_) => "configurable",
843            ConstGenericDecl(_) => "const generic",
844            TraitTypeDecl(_) => "type",
845            FunctionDecl(_) => "function",
846            TraitDecl(_) => "trait",
847            StructDecl(_) => "struct",
848            EnumDecl(_) => "enum",
849            EnumVariantDecl(_) => "enum variant",
850            ImplSelfOrTrait(_) => "impl trait",
851            AbiDecl(_) => "abi",
852            GenericTypeForFunctionScope(_) => "generic type parameter",
853            ErrorRecovery(_, _) => "error",
854            StorageDecl(_) => "contract storage",
855            TypeAliasDecl(_) => "type alias",
856        }
857    }
858
859    pub fn friendly_type_name_with_acronym(&self) -> &'static str {
860        match self.friendly_type_name() {
861            "abi" => "ABI",
862            friendly_name => friendly_name,
863        }
864    }
865
866    pub(crate) fn return_type(
867        &self,
868        handler: &Handler,
869        engines: &Engines,
870    ) -> Result<TypeId, ErrorEmitted> {
871        let type_engine = engines.te();
872        let decl_engine = engines.de();
873        let type_id = match self {
874            TyDecl::VariableDecl(decl) => decl.return_type,
875            TyDecl::FunctionDecl(FunctionDecl { decl_id, .. }) => {
876                let decl = decl_engine.get_function(decl_id);
877                decl.return_type.type_id
878            }
879            TyDecl::StructDecl(StructDecl { decl_id }) => {
880                type_engine.insert_struct(engines, *decl_id)
881            }
882            TyDecl::EnumDecl(EnumDecl { decl_id }) => type_engine.insert_enum(engines, *decl_id),
883            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id, .. }) => {
884                let decl = decl_engine.get_type_alias(decl_id);
885                decl.create_type_id(engines)
886            }
887            TyDecl::GenericTypeForFunctionScope(GenericTypeForFunctionScope {
888                type_id, ..
889            }) => *type_id,
890            decl => {
891                return Err(handler.emit_err(CompileError::NotAType {
892                    span: decl.span(engines),
893                    name: engines.help_out(decl).to_string(),
894                    actually_is: decl.friendly_type_name(),
895                }));
896            }
897        };
898        Ok(type_id)
899    }
900
901    pub(crate) fn visibility(&self, decl_engine: &DeclEngine) -> Visibility {
902        match self {
903            TyDecl::TraitDecl(TraitDecl { decl_id, .. }) => {
904                decl_engine.get_trait(decl_id).visibility
905            }
906            TyDecl::ConstantDecl(ConstantDecl { decl_id, .. }) => {
907                decl_engine.get_constant(decl_id).visibility
908            }
909            TyDecl::ConfigurableDecl(ConfigurableDecl { decl_id, .. }) => {
910                decl_engine.get_configurable(decl_id).visibility
911            }
912            TyDecl::ConstGenericDecl(_) => {
913                unreachable!("Const generics do not have visibility");
914            }
915            TyDecl::StructDecl(StructDecl { decl_id, .. }) => {
916                decl_engine.get_struct(decl_id).visibility
917            }
918            TyDecl::EnumDecl(EnumDecl { decl_id, .. }) => decl_engine.get_enum(decl_id).visibility,
919            TyDecl::EnumVariantDecl(EnumVariantDecl { enum_ref, .. }) => {
920                decl_engine.get_enum(enum_ref.id()).visibility
921            }
922            TyDecl::FunctionDecl(FunctionDecl { decl_id, .. }) => {
923                decl_engine.get_function(decl_id).visibility
924            }
925            TyDecl::TypeAliasDecl(TypeAliasDecl { decl_id, .. }) => {
926                decl_engine.get_type_alias(decl_id).visibility
927            }
928            TyDecl::GenericTypeForFunctionScope(_)
929            | TyDecl::ImplSelfOrTrait(_)
930            | TyDecl::StorageDecl(_)
931            | TyDecl::AbiDecl(_)
932            | TyDecl::TraitTypeDecl(_)
933            | TyDecl::ErrorRecovery(_, _) => Visibility::Public,
934            TyDecl::VariableDecl(decl) => decl.mutability.visibility(),
935        }
936    }
937}
938
939impl From<DeclRef<DeclId<TyTraitType>>> for TyDecl {
940    fn from(decl_ref: DeclRef<DeclId<TyTraitType>>) -> Self {
941        TyDecl::TraitTypeDecl(TraitTypeDecl {
942            decl_id: *decl_ref.id(),
943        })
944    }
945}
946
947impl From<DeclRef<DeclId<TyConstantDecl>>> for TyDecl {
948    fn from(decl_ref: DeclRef<DeclId<TyConstantDecl>>) -> Self {
949        TyDecl::ConstantDecl(ConstantDecl {
950            decl_id: *decl_ref.id(),
951        })
952    }
953}
954
955impl From<DeclRef<DeclId<TyConfigurableDecl>>> for TyDecl {
956    fn from(decl_ref: DeclRef<DeclId<TyConfigurableDecl>>) -> Self {
957        TyDecl::ConfigurableDecl(ConfigurableDecl {
958            decl_id: *decl_ref.id(),
959        })
960    }
961}
962
963impl From<DeclRef<DeclId<TyEnumDecl>>> for TyDecl {
964    fn from(decl_ref: DeclRef<DeclId<TyEnumDecl>>) -> Self {
965        TyDecl::EnumDecl(EnumDecl {
966            decl_id: *decl_ref.id(),
967        })
968    }
969}
970
971impl From<DeclRef<DeclId<TyFunctionDecl>>> for TyDecl {
972    fn from(decl_ref: DeclRef<DeclId<TyFunctionDecl>>) -> Self {
973        TyDecl::FunctionDecl(FunctionDecl {
974            decl_id: *decl_ref.id(),
975        })
976    }
977}
978
979impl From<DeclRef<DeclId<TyTraitDecl>>> for TyDecl {
980    fn from(decl_ref: DeclRef<DeclId<TyTraitDecl>>) -> Self {
981        TyDecl::TraitDecl(TraitDecl {
982            decl_id: *decl_ref.id(),
983        })
984    }
985}
986
987impl From<DeclRef<DeclId<TyImplSelfOrTrait>>> for TyDecl {
988    fn from(decl_ref: DeclRef<DeclId<TyImplSelfOrTrait>>) -> Self {
989        TyDecl::ImplSelfOrTrait(ImplSelfOrTrait {
990            decl_id: *decl_ref.id(),
991        })
992    }
993}
994
995impl From<DeclRef<DeclId<TyStructDecl>>> for TyDecl {
996    fn from(decl_ref: DeclRef<DeclId<TyStructDecl>>) -> Self {
997        TyDecl::StructDecl(StructDecl {
998            decl_id: *decl_ref.id(),
999        })
1000    }
1001}
1002
1003impl From<DeclRef<DeclId<TyAbiDecl>>> for TyDecl {
1004    fn from(decl_ref: DeclRef<DeclId<TyAbiDecl>>) -> Self {
1005        TyDecl::AbiDecl(AbiDecl {
1006            decl_id: *decl_ref.id(),
1007        })
1008    }
1009}
1010
1011impl From<DeclRef<DeclId<TyStorageDecl>>> for TyDecl {
1012    fn from(decl_ref: DeclRef<DeclId<TyStorageDecl>>) -> Self {
1013        TyDecl::StorageDecl(StorageDecl {
1014            decl_id: *decl_ref.id(),
1015        })
1016    }
1017}
1018impl From<DeclRef<DeclId<TyTypeAliasDecl>>> for TyDecl {
1019    fn from(decl_ref: DeclRef<DeclId<TyTypeAliasDecl>>) -> Self {
1020        TyDecl::TypeAliasDecl(TypeAliasDecl {
1021            decl_id: *decl_ref.id(),
1022        })
1023    }
1024}