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(_) => {
127                todo!("Will be implemented by https://github.com/FuelLabs/sway/issues/6860")
128            }
129        }
130    }
131
132    pub(crate) fn to_fn_ref(
133        &self,
134        handler: &Handler,
135        engines: &Engines,
136    ) -> Result<ParsedDeclId<FunctionDeclaration>, ErrorEmitted> {
137        match self {
138            Declaration::FunctionDeclaration(decl_id) => Ok(*decl_id),
139            decl => Err(handler.emit_err(CompileError::DeclIsNotAFunction {
140                actually: decl.friendly_type_name().to_string(),
141                span: decl.span(engines),
142            })),
143        }
144    }
145
146    pub(crate) fn to_struct_decl(
147        &self,
148        handler: &Handler,
149        engines: &Engines,
150    ) -> Result<ParsedDeclId<StructDeclaration>, ErrorEmitted> {
151        match self {
152            Declaration::StructDeclaration(decl_id) => Ok(*decl_id),
153            Declaration::TypeAliasDeclaration(decl_id) => {
154                let alias = engines.pe().get_type_alias(decl_id);
155                let struct_decl_id = engines.te().get(alias.ty.type_id).expect_struct(
156                    handler,
157                    engines,
158                    &self.span(engines),
159                )?;
160
161                let parsed_decl_id = engines.de().get_parsed_decl_id(&struct_decl_id);
162                parsed_decl_id.ok_or_else(|| {
163                    handler.emit_err(CompileError::InternalOwned(
164                        "Cannot get parsed decl id from decl id".to_string(),
165                        self.span(engines),
166                    ))
167                })
168            }
169            decl => Err(handler.emit_err(CompileError::DeclIsNotAStruct {
170                actually: decl.friendly_type_name().to_string(),
171                span: decl.span(engines),
172            })),
173        }
174    }
175
176    #[allow(unused)]
177    pub(crate) fn visibility(&self, decl_engine: &ParsedDeclEngine) -> Visibility {
178        match self {
179            Declaration::TraitDeclaration(decl_id) => decl_engine.get_trait(decl_id).visibility,
180            Declaration::ConstantDeclaration(decl_id) => {
181                decl_engine.get_constant(decl_id).visibility
182            }
183            Declaration::ConfigurableDeclaration(decl_id) => {
184                decl_engine.get_configurable(decl_id).visibility
185            }
186            Declaration::StructDeclaration(decl_id) => decl_engine.get_struct(decl_id).visibility,
187            Declaration::EnumDeclaration(decl_id) => decl_engine.get_enum(decl_id).visibility,
188            Declaration::EnumVariantDeclaration(decl) => {
189                decl_engine.get_enum(&decl.enum_ref).visibility
190            }
191            Declaration::FunctionDeclaration(decl_id) => {
192                decl_engine.get_function(decl_id).visibility
193            }
194            Declaration::TypeAliasDeclaration(decl_id) => {
195                decl_engine.get_type_alias(decl_id).visibility
196            }
197            Declaration::VariableDeclaration(_decl_id) => Visibility::Private,
198            Declaration::ImplSelfOrTrait(_)
199            | Declaration::StorageDeclaration(_)
200            | Declaration::AbiDeclaration(_)
201            | Declaration::TraitTypeDeclaration(_)
202            | Declaration::TraitFnDeclaration(_) => Visibility::Public,
203            Declaration::ConstGenericDeclaration(_) => {
204                todo!("Will be implemented by https://github.com/FuelLabs/sway/issues/6860")
205            }
206        }
207    }
208}
209
210impl DisplayWithEngines for Declaration {
211    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> std::fmt::Result {
212        write!(
213            f,
214            "{} parsed declaration ({})",
215            self.friendly_type_name(),
216            match self {
217                Declaration::VariableDeclaration(decl_id) => {
218                    engines.pe().get(decl_id).name.as_str().into()
219                }
220                Declaration::FunctionDeclaration(decl_id) => {
221                    engines.pe().get(decl_id).name.as_str().into()
222                }
223                Declaration::TraitDeclaration(decl_id) => {
224                    engines.pe().get(decl_id).name.as_str().into()
225                }
226                Declaration::StructDeclaration(decl_id) => {
227                    engines.pe().get(decl_id).name.as_str().into()
228                }
229                Declaration::EnumDeclaration(decl_id) => {
230                    engines.pe().get(decl_id).name.as_str().into()
231                }
232                Declaration::ImplSelfOrTrait(decl_id) => {
233                    engines
234                        .pe()
235                        .get(decl_id)
236                        .trait_name
237                        .as_vec_string()
238                        .join("::")
239                        .as_str()
240                        .into()
241                }
242                Declaration::TypeAliasDeclaration(decl_id) =>
243                    engines.pe().get(decl_id).name.as_str().into(),
244                _ => String::new(),
245            }
246        )
247    }
248}
249
250impl DebugWithEngines for Declaration {
251    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> std::fmt::Result {
252        DisplayWithEngines::fmt(&self, f, engines)
253    }
254}
255
256impl EqWithEngines for Declaration {}
257impl PartialEqWithEngines for Declaration {
258    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
259        let decl_engine = ctx.engines().pe();
260        match (self, other) {
261            (Declaration::VariableDeclaration(lid), Declaration::VariableDeclaration(rid)) => {
262                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
263            }
264            (Declaration::FunctionDeclaration(lid), Declaration::FunctionDeclaration(rid)) => {
265                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
266            }
267            (Declaration::TraitDeclaration(lid), Declaration::TraitDeclaration(rid)) => {
268                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
269            }
270            (Declaration::StructDeclaration(lid), Declaration::StructDeclaration(rid)) => {
271                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
272            }
273            (Declaration::EnumDeclaration(lid), Declaration::EnumDeclaration(rid)) => {
274                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
275            }
276            (Declaration::ImplSelfOrTrait(lid), Declaration::ImplSelfOrTrait(rid)) => {
277                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
278            }
279            (Declaration::AbiDeclaration(lid), Declaration::AbiDeclaration(rid)) => {
280                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
281            }
282            (Declaration::ConstantDeclaration(lid), Declaration::ConstantDeclaration(rid)) => {
283                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
284            }
285            (Declaration::StorageDeclaration(lid), Declaration::StorageDeclaration(rid)) => {
286                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
287            }
288            (Declaration::TypeAliasDeclaration(lid), Declaration::TypeAliasDeclaration(rid)) => {
289                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
290            }
291            (Declaration::TraitTypeDeclaration(lid), Declaration::TraitTypeDeclaration(rid)) => {
292                decl_engine.get(lid).eq(&decl_engine.get(rid), ctx)
293            }
294            _ => false,
295        }
296    }
297}