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