Skip to main content

sway_core/language/ty/declaration/
declaration.rs

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