sway_core/language/parsed/
declaration.rs

1mod abi;
2mod configurable;
3mod const_generic;
4mod constant;
5mod r#enum;
6pub mod function;
7mod impl_trait;
8mod storage;
9mod r#struct;
10mod r#trait;
11mod type_alias;
12mod variable;
13
14use std::fmt;
15
16pub use abi::*;
17pub use configurable::*;
18pub use const_generic::*;
19pub use constant::*;
20pub use function::*;
21pub use impl_trait::*;
22pub use r#enum::*;
23pub use r#struct::*;
24pub use r#trait::*;
25pub use storage::*;
26use sway_error::{
27    error::CompileError,
28    handler::{ErrorEmitted, Handler},
29};
30use sway_types::{Ident, Span, Spanned};
31pub use type_alias::*;
32pub use variable::*;
33
34use crate::{
35    decl_engine::{
36        parsed_engine::{ParsedDeclEngine, ParsedDeclEngineGet},
37        parsed_id::ParsedDeclId,
38        DeclEngineGetParsedDeclId,
39    },
40    engine_threading::{
41        DebugWithEngines, DisplayWithEngines, EqWithEngines, PartialEqWithEngines,
42        PartialEqWithEnginesContext,
43    },
44    language::Visibility,
45    Engines,
46};
47
48#[derive(Debug, Clone)]
49pub enum Declaration {
50    VariableDeclaration(ParsedDeclId<VariableDeclaration>),
51    FunctionDeclaration(ParsedDeclId<FunctionDeclaration>),
52    TraitDeclaration(ParsedDeclId<TraitDeclaration>),
53    StructDeclaration(ParsedDeclId<StructDeclaration>),
54    EnumDeclaration(ParsedDeclId<EnumDeclaration>),
55    EnumVariantDeclaration(EnumVariantDeclaration),
56    ImplSelfOrTrait(ParsedDeclId<ImplSelfOrTrait>),
57    AbiDeclaration(ParsedDeclId<AbiDeclaration>),
58    ConstantDeclaration(ParsedDeclId<ConstantDeclaration>),
59    ConfigurableDeclaration(ParsedDeclId<ConfigurableDeclaration>),
60    StorageDeclaration(ParsedDeclId<StorageDeclaration>),
61    TypeAliasDeclaration(ParsedDeclId<TypeAliasDeclaration>),
62    TraitTypeDeclaration(ParsedDeclId<TraitTypeDeclaration>),
63    TraitFnDeclaration(ParsedDeclId<TraitFn>),
64    ConstGenericDeclaration(ParsedDeclId<ConstGenericDeclaration>),
65}
66
67#[derive(Debug, Clone)]
68pub struct EnumVariantDeclaration {
69    pub enum_ref: ParsedDeclId<EnumDeclaration>,
70    pub variant_name: Ident,
71    pub variant_decl_span: Span,
72}
73
74impl Declaration {
75    /// Checks if this `Declaration` is a test.
76    pub(crate) fn is_test(&self, engines: &Engines) -> bool {
77        if let Declaration::FunctionDeclaration(fn_decl) = self {
78            let fn_decl = engines.pe().get_function(fn_decl);
79            fn_decl.is_test()
80        } else {
81            false
82        }
83    }
84
85    /// Friendly type name string used for error reporting,
86    /// which consists of the type name of the declaration AST node.
87    pub fn friendly_type_name(&self) -> &'static str {
88        use Declaration::*;
89        match self {
90            VariableDeclaration(_) => "variable",
91            ConstantDeclaration(_) => "constant",
92            ConfigurableDeclaration(_) => "configurable",
93            TraitTypeDeclaration(_) => "type",
94            FunctionDeclaration(_) => "function",
95            TraitDeclaration(_) => "trait",
96            TraitFnDeclaration(_) => "trait fn",
97            StructDeclaration(_) => "struct",
98            EnumDeclaration(_) => "enum",
99            EnumVariantDeclaration(_) => "enum variant",
100            ImplSelfOrTrait(_) => "impl self/trait",
101            AbiDeclaration(_) => "abi",
102            StorageDeclaration(_) => "contract storage",
103            TypeAliasDeclaration(_) => "type alias",
104            ConstGenericDeclaration(_) => "const generic",
105        }
106    }
107
108    pub fn span(&self, engines: &Engines) -> sway_types::Span {
109        use Declaration::*;
110        let pe = engines.pe();
111        match self {
112            VariableDeclaration(decl_id) => pe.get_variable(decl_id).span(),
113            FunctionDeclaration(decl_id) => pe.get_function(decl_id).span(),
114            TraitDeclaration(decl_id) => pe.get_trait(decl_id).span(),
115            StructDeclaration(decl_id) => pe.get_struct(decl_id).span(),
116            EnumDeclaration(decl_id) => pe.get_enum(decl_id).span(),
117            EnumVariantDeclaration(decl) => decl.variant_decl_span.clone(),
118            ImplSelfOrTrait(decl_id) => pe.get_impl_self_or_trait(decl_id).span(),
119            AbiDeclaration(decl_id) => pe.get_abi(decl_id).span(),
120            ConstantDeclaration(decl_id) => pe.get_constant(decl_id).span(),
121            ConfigurableDeclaration(decl_id) => pe.get_configurable(decl_id).span(),
122            StorageDeclaration(decl_id) => pe.get_storage(decl_id).span(),
123            TypeAliasDeclaration(decl_id) => pe.get_type_alias(decl_id).span(),
124            TraitTypeDeclaration(decl_id) => pe.get_trait_type(decl_id).span(),
125            TraitFnDeclaration(decl_id) => pe.get_trait_fn(decl_id).span(),
126            ConstGenericDeclaration(decl_id) => pe.get_const_generic(decl_id).span(),
127        }
128    }
129
130    pub(crate) fn to_fn_ref(
131        &self,
132        handler: &Handler,
133        engines: &Engines,
134    ) -> Result<ParsedDeclId<FunctionDeclaration>, ErrorEmitted> {
135        match self {
136            Declaration::FunctionDeclaration(decl_id) => Ok(*decl_id),
137            decl => Err(handler.emit_err(CompileError::DeclIsNotAFunction {
138                actually: decl.friendly_type_name().to_string(),
139                span: decl.span(engines),
140            })),
141        }
142    }
143
144    pub(crate) fn to_struct_decl(
145        &self,
146        handler: &Handler,
147        engines: &Engines,
148    ) -> Result<ParsedDeclId<StructDeclaration>, ErrorEmitted> {
149        match self {
150            Declaration::StructDeclaration(decl_id) => Ok(*decl_id),
151            Declaration::TypeAliasDeclaration(decl_id) => {
152                let alias = engines.pe().get_type_alias(decl_id);
153                let struct_decl_id = engines.te().get(alias.ty.type_id).expect_struct(
154                    handler,
155                    engines,
156                    &self.span(engines),
157                )?;
158
159                let parsed_decl_id = engines.de().get_parsed_decl_id(&struct_decl_id);
160                parsed_decl_id.ok_or_else(|| {
161                    handler.emit_err(CompileError::InternalOwned(
162                        "Cannot get parsed decl id from decl id".to_string(),
163                        self.span(engines),
164                    ))
165                })
166            }
167            decl => Err(handler.emit_err(CompileError::DeclIsNotAStruct {
168                actually: decl.friendly_type_name().to_string(),
169                span: decl.span(engines),
170            })),
171        }
172    }
173
174    pub(crate) fn to_enum_decl(
175        &self,
176        handler: &Handler,
177        engines: &Engines,
178    ) -> Result<ParsedDeclId<EnumDeclaration>, ErrorEmitted> {
179        match self {
180            Declaration::EnumDeclaration(decl_id) => Ok(*decl_id),
181            Declaration::TypeAliasDeclaration(decl_id) => {
182                let alias = engines.pe().get_type_alias(decl_id);
183                let enum_decl_id = engines.te().get(alias.ty.type_id).expect_enum(
184                    handler,
185                    engines,
186                    String::default(),
187                    &self.span(engines),
188                )?;
189
190                let parsed_decl_id = engines.de().get_parsed_decl_id(&enum_decl_id);
191                parsed_decl_id.ok_or_else(|| {
192                    handler.emit_err(CompileError::InternalOwned(
193                        "Cannot get parsed decl id from decl id".to_string(),
194                        self.span(engines),
195                    ))
196                })
197            }
198            decl => Err(handler.emit_err(CompileError::DeclIsNotAnEnum {
199                actually: decl.friendly_type_name().to_string(),
200                span: decl.span(engines),
201            })),
202        }
203    }
204
205    #[allow(unused)]
206    pub(crate) fn visibility(&self, decl_engine: &ParsedDeclEngine) -> Visibility {
207        match self {
208            Declaration::TraitDeclaration(decl_id) => decl_engine.get_trait(decl_id).visibility,
209            Declaration::ConstantDeclaration(decl_id) => {
210                decl_engine.get_constant(decl_id).visibility
211            }
212            Declaration::ConfigurableDeclaration(decl_id) => {
213                decl_engine.get_configurable(decl_id).visibility
214            }
215            Declaration::StructDeclaration(decl_id) => decl_engine.get_struct(decl_id).visibility,
216            Declaration::EnumDeclaration(decl_id) => decl_engine.get_enum(decl_id).visibility,
217            Declaration::EnumVariantDeclaration(decl) => {
218                decl_engine.get_enum(&decl.enum_ref).visibility
219            }
220            Declaration::FunctionDeclaration(decl_id) => {
221                decl_engine.get_function(decl_id).visibility
222            }
223            Declaration::TypeAliasDeclaration(decl_id) => {
224                decl_engine.get_type_alias(decl_id).visibility
225            }
226            Declaration::VariableDeclaration(_decl_id) => Visibility::Private,
227            Declaration::ImplSelfOrTrait(_)
228            | Declaration::StorageDeclaration(_)
229            | Declaration::AbiDeclaration(_)
230            | Declaration::TraitTypeDeclaration(_)
231            | Declaration::TraitFnDeclaration(_) => Visibility::Public,
232            Declaration::ConstGenericDeclaration(_) => {
233                unreachable!("Const generics do not have visibility")
234            }
235        }
236    }
237}
238
239impl DisplayWithEngines for Declaration {
240    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> std::fmt::Result {
241        write!(
242            f,
243            "{} parsed declaration ({})",
244            self.friendly_type_name(),
245            match self {
246                Declaration::VariableDeclaration(decl_id) => {
247                    engines.pe().get(decl_id).name.as_str().into()
248                }
249                Declaration::FunctionDeclaration(decl_id) => {
250                    engines.pe().get(decl_id).name.as_str().into()
251                }
252                Declaration::TraitDeclaration(decl_id) => {
253                    engines.pe().get(decl_id).name.as_str().into()
254                }
255                Declaration::StructDeclaration(decl_id) => {
256                    engines.pe().get(decl_id).name.as_str().into()
257                }
258                Declaration::EnumDeclaration(decl_id) => {
259                    engines.pe().get(decl_id).name.as_str().into()
260                }
261                Declaration::ImplSelfOrTrait(decl_id) => {
262                    engines
263                        .pe()
264                        .get(decl_id)
265                        .trait_name
266                        .as_vec_string()
267                        .join("::")
268                        .as_str()
269                        .into()
270                }
271                Declaration::TypeAliasDeclaration(decl_id) =>
272                    engines.pe().get(decl_id).name.as_str().into(),
273                _ => String::new(),
274            }
275        )
276    }
277}
278
279impl DebugWithEngines for Declaration {
280    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> std::fmt::Result {
281        DisplayWithEngines::fmt(&self, f, engines)
282    }
283}
284
285impl EqWithEngines for Declaration {}
286impl PartialEqWithEngines for Declaration {
287    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
288        let decl_engine = ctx.engines().pe();
289        match (self, other) {
290            (Declaration::VariableDeclaration(lid), Declaration::VariableDeclaration(rid)) => {
291                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
292            }
293            (Declaration::FunctionDeclaration(lid), Declaration::FunctionDeclaration(rid)) => {
294                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
295            }
296            (Declaration::TraitDeclaration(lid), Declaration::TraitDeclaration(rid)) => {
297                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
298            }
299            (Declaration::StructDeclaration(lid), Declaration::StructDeclaration(rid)) => {
300                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
301            }
302            (Declaration::EnumDeclaration(lid), Declaration::EnumDeclaration(rid)) => {
303                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
304            }
305            (Declaration::ImplSelfOrTrait(lid), Declaration::ImplSelfOrTrait(rid)) => {
306                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
307            }
308            (Declaration::AbiDeclaration(lid), Declaration::AbiDeclaration(rid)) => {
309                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
310            }
311            (Declaration::ConstantDeclaration(lid), Declaration::ConstantDeclaration(rid)) => {
312                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
313            }
314            (Declaration::StorageDeclaration(lid), Declaration::StorageDeclaration(rid)) => {
315                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
316            }
317            (Declaration::TypeAliasDeclaration(lid), Declaration::TypeAliasDeclaration(rid)) => {
318                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
319            }
320            (Declaration::TraitTypeDeclaration(lid), Declaration::TraitTypeDeclaration(rid)) => {
321                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
322            }
323            _ => false,
324        }
325    }
326}