sway_core/semantic_analysis/namespace/
lexical_scope.rs

1use crate::{
2    decl_engine::{parsed_engine::ParsedDeclEngineGet, parsed_id::ParsedDeclId, *},
3    engine_threading::{Engines, PartialEqWithEngines, PartialEqWithEnginesContext},
4    language::{
5        parsed::{Declaration, FunctionDeclaration},
6        ty::{self, TyDecl, TyStorageDecl},
7        Visibility,
8    },
9    namespace::*,
10    semantic_analysis::{ast_node::ConstShadowingMode, GenericShadowingMode},
11    type_system::*,
12};
13
14use super::{ResolvedDeclaration, TraitMap};
15
16use parking_lot::RwLock;
17use sway_error::{
18    error::{CompileError, ShadowingSource},
19    handler::{ErrorEmitted, Handler},
20};
21use sway_types::{span::Span, IdentUnique, Named, Spanned};
22
23use std::{collections::HashMap, sync::Arc};
24
25pub enum ResolvedFunctionDecl {
26    Parsed(ParsedDeclId<FunctionDeclaration>),
27    Typed(DeclRefFunction),
28}
29
30impl ResolvedFunctionDecl {
31    pub fn expect_typed(self) -> DeclRefFunction {
32        match self {
33            ResolvedFunctionDecl::Parsed(_) => panic!(),
34            ResolvedFunctionDecl::Typed(fn_ref) => fn_ref,
35        }
36    }
37}
38
39// The following types were using im::OrdMap but it revealed to be
40// much slower than using HashMap and sorting on iterationn.
41pub(super) type SymbolMap = HashMap<Ident, ResolvedDeclaration>;
42pub(super) type SymbolUniqueMap = HashMap<IdentUnique, ResolvedDeclaration>;
43
44type SourceIdent = Ident;
45
46pub(super) type PreludeSynonyms = HashMap<Ident, (ModulePathBuf, ResolvedDeclaration)>;
47pub(super) type GlobSynonyms =
48    HashMap<Ident, Vec<(ModulePathBuf, ResolvedDeclaration, Visibility)>>;
49pub(super) type ItemSynonyms = HashMap<
50    Ident,
51    (
52        Option<SourceIdent>,
53        ModulePathBuf,
54        ResolvedDeclaration,
55        Visibility,
56    ),
57>;
58
59/// Represents a lexical scope integer-based identifier, which can be used to reference
60/// specific a lexical scope.
61pub type LexicalScopeId = usize;
62
63/// Represents a lexical scope path, a vector of lexical scope identifiers, which specifies
64/// the path from root to a specific lexical scope in the hierarchy.
65pub type LexicalScopePath = Vec<LexicalScopeId>;
66
67/// A `LexicalScope` contains a set of all items that exist within the lexical scope via declaration or
68/// importing, along with all its associated hierarchical scopes.
69#[derive(Clone, Debug, Default)]
70pub struct LexicalScope {
71    /// The set of symbols, implementations, synonyms and aliases present within this scope.
72    pub items: Items,
73    /// The set of available scopes defined inside this scope's hierarchy.
74    pub children: Vec<LexicalScopeId>,
75    /// The parent scope associated with this scope. Will be None for a root scope.
76    pub parent: Option<LexicalScopeId>,
77    /// The parent while visiting scopes and push popping scopes from a stack.
78    /// This may differ from parent as we may revisit the scope in a different order during type check.
79    pub visitor_parent: Option<LexicalScopeId>,
80    /// The declaration associated with this scope. This will initially be a [ParsedDeclId],
81    /// but can be replaced to be a [DeclId] once the declaration is type checked.
82    pub declaration: Option<ResolvedDeclaration>,
83}
84
85/// The set of items that exist within some lexical scope via declaration or importing.
86#[derive(Clone, Debug, Default)]
87pub struct Items {
88    /// An map from `Ident`s to their associated declarations.
89    pub(crate) symbols: SymbolMap,
90
91    /// An map from `IdentUnique`s to their associated declarations.
92    /// This uses an Arc<RwLock<SymbolUniqueMap>> so it is shared between all
93    /// Items clones. This is intended so we can keep the symbols of previous
94    /// lexical scopes while collecting_unifications scopes.
95    pub(crate) symbols_unique_while_collecting_unifications: Arc<RwLock<SymbolUniqueMap>>,
96
97    pub(crate) implemented_traits: TraitMap,
98    /// Contains symbols imported from the standard library preludes.
99    ///
100    /// The import are asserted to never have a name clash. The imported names are always private
101    /// rather than public (`use ...` rather than `pub use ...`), since the bindings cannot be
102    /// accessed from outside the importing module. The preludes are asserted to not contain name
103    /// clashes.
104    pub(crate) prelude_synonyms: PreludeSynonyms,
105    /// Contains symbols imported using star imports (`use foo::*`.).
106    ///
107    /// When star importing from multiple modules the same name may be imported more than once. This
108    /// is not an error, but it is an error to use the name without a module path. To represent
109    /// this, use_glob_synonyms maps identifiers to a vector of (module path, type declaration)
110    /// tuples.
111    pub(crate) use_glob_synonyms: GlobSynonyms,
112    /// Contains symbols imported using item imports (`use foo::bar`).
113    ///
114    /// For aliased item imports `use ::foo::bar::Baz as Wiz` the map key is `Wiz`. `Baz` is stored
115    /// as the optional source identifier for error reporting purposes.
116    pub(crate) use_item_synonyms: ItemSynonyms,
117    /// If there is a storage declaration (which are only valid in contracts), store it here.
118    pub(crate) declared_storage: Option<DeclRefStorage>,
119}
120
121impl Items {
122    /// Immutable access to the inner symbol map.
123    pub fn symbols(&self) -> &SymbolMap {
124        &self.symbols
125    }
126
127    #[allow(clippy::too_many_arguments)]
128    pub fn apply_storage_load(
129        &self,
130        handler: &Handler,
131        engines: &Engines,
132        namespace: &Namespace,
133        namespace_names: &[Ident],
134        fields: &[Ident],
135        storage_fields: &[ty::TyStorageField],
136        storage_keyword_span: Span,
137    ) -> Result<(ty::TyStorageAccess, TypeId), ErrorEmitted> {
138        match self.declared_storage {
139            Some(ref decl_ref) => {
140                let storage = engines.de().get_storage(&decl_ref.id().clone());
141                storage.apply_storage_load(
142                    handler,
143                    engines,
144                    namespace,
145                    namespace_names,
146                    fields,
147                    storage_fields,
148                    storage_keyword_span,
149                )
150            }
151            None => Err(handler.emit_err(CompileError::NoDeclaredStorage {
152                span: fields[0].span(),
153            })),
154        }
155    }
156
157    pub fn set_storage_declaration(
158        &mut self,
159        handler: &Handler,
160        decl_ref: DeclRefStorage,
161    ) -> Result<(), ErrorEmitted> {
162        if self.declared_storage.is_some() {
163            return Err(handler.emit_err(CompileError::MultipleStorageDeclarations {
164                span: decl_ref.span(),
165            }));
166        }
167        self.declared_storage = Some(decl_ref);
168        Ok(())
169    }
170
171    pub fn get_all_declared_symbols(&self) -> Vec<&Ident> {
172        let mut keys: Vec<_> = self.symbols().keys().collect();
173        keys.sort();
174        keys
175    }
176
177    pub fn resolve_symbol(
178        &self,
179        handler: &Handler,
180        engines: &Engines,
181        symbol: &Ident,
182        current_mod_path: &ModulePathBuf,
183    ) -> Result<Option<(ResolvedDeclaration, ModulePathBuf)>, ErrorEmitted> {
184        // Check locally declared items. Any name clash with imports will have already been reported as an error.
185        if let Some(decl) = self.symbols.get(symbol) {
186            return Ok(Some((decl.clone(), current_mod_path.clone())));
187        }
188
189        // Check item imports
190        if let Some((_, decl_path, decl, _)) = self.use_item_synonyms.get(symbol) {
191            return Ok(Some((decl.clone(), decl_path.clone())));
192        }
193
194        // Check glob imports
195        if let Some(decls) = self.use_glob_synonyms.get(symbol) {
196            if decls.len() == 1 {
197                return Ok(Some((decls[0].1.clone(), decls[0].0.clone())));
198            } else if decls.is_empty() {
199                return Err(handler.emit_err(CompileError::Internal(
200                    "The name {symbol} was bound in a star import, but no corresponding module paths were found",
201                    symbol.span(),
202                )));
203            } else {
204                return Err(handler.emit_err(CompileError::SymbolWithMultipleBindings {
205                    name: symbol.clone(),
206                    paths: decls
207                        .iter()
208                        .map(|(path, decl, _)| {
209                            get_path_for_decl(path, decl, engines, &current_mod_path[0]).join("::")
210                        })
211                        .collect(),
212                    span: symbol.span(),
213                }));
214            }
215        }
216
217        // Check prelude imports
218        if let Some((decl_path, decl)) = self.prelude_synonyms.get(symbol) {
219            return Ok(Some((decl.clone(), decl_path.clone())));
220        }
221
222        Ok(None)
223    }
224
225    pub(crate) fn insert_parsed_symbol(
226        handler: &Handler,
227        engines: &Engines,
228        module: &mut Module,
229        name: Ident,
230        item: Declaration,
231        const_shadowing_mode: ConstShadowingMode,
232        generic_shadowing_mode: GenericShadowingMode,
233    ) -> Result<(), ErrorEmitted> {
234        Self::insert_symbol(
235            handler,
236            engines,
237            module,
238            name,
239            ResolvedDeclaration::Parsed(item),
240            const_shadowing_mode,
241            generic_shadowing_mode,
242            false,
243        )
244    }
245
246    #[allow(clippy::too_many_arguments)]
247    pub(crate) fn insert_typed_symbol(
248        handler: &Handler,
249        engines: &Engines,
250        module: &mut Module,
251        name: Ident,
252        item: ty::TyDecl,
253        const_shadowing_mode: ConstShadowingMode,
254        generic_shadowing_mode: GenericShadowingMode,
255        collecting_unifications: bool,
256    ) -> Result<(), ErrorEmitted> {
257        Self::insert_symbol(
258            handler,
259            engines,
260            module,
261            name,
262            ResolvedDeclaration::Typed(item),
263            const_shadowing_mode,
264            generic_shadowing_mode,
265            collecting_unifications,
266        )
267    }
268
269    #[allow(clippy::too_many_arguments)]
270    pub(crate) fn insert_symbol(
271        handler: &Handler,
272        engines: &Engines,
273        module: &mut Module,
274        name: Ident,
275        item: ResolvedDeclaration,
276        const_shadowing_mode: ConstShadowingMode,
277        generic_shadowing_mode: GenericShadowingMode,
278        collecting_unifications: bool,
279    ) -> Result<(), ErrorEmitted> {
280        let parsed_decl_engine = engines.pe();
281        let decl_engine = engines.de();
282
283        #[allow(unused)]
284        let append_shadowing_error_parsed =
285            |ident: &Ident,
286             decl: &Declaration,
287             is_use: bool,
288             is_alias: bool,
289             item: &Declaration,
290             const_shadowing_mode: ConstShadowingMode| {
291                use Declaration::*;
292                match (
293                    ident,
294                    decl,
295                    is_use,
296                    is_alias,
297                    &item,
298                    const_shadowing_mode,
299                    generic_shadowing_mode,
300                ) {
301                    // A general remark for using the `ShadowingSource::LetVar`.
302                    // If the shadowing is detected at this stage, the variable is for
303                    // sure a local variable, because in the case of pattern matching
304                    // struct field variables, the error is already reported and
305                    // the compilation do not proceed to the point of inserting
306                    // the pattern variable into the items.
307
308                    // variable shadowing a constant
309                    (
310                        constant_ident,
311                        ConstantDeclaration(decl_id),
312                        is_imported_constant,
313                        is_alias,
314                        VariableDeclaration { .. },
315                        _,
316                        _,
317                    ) => {
318                        handler.emit_err(CompileError::ConstantsCannotBeShadowed {
319                            shadowing_source: ShadowingSource::LetVar,
320                            name: (&name).into(),
321                            constant_span: constant_ident.span(),
322                            constant_decl_span: if is_imported_constant {
323                                parsed_decl_engine.get(decl_id).span.clone()
324                            } else {
325                                Span::dummy()
326                            },
327                            is_alias,
328                        });
329                    }
330                    // variable shadowing a configurable
331                    (
332                        configurable_ident,
333                        ConfigurableDeclaration(_),
334                        _,
335                        _,
336                        VariableDeclaration { .. },
337                        _,
338                        _,
339                    ) => {
340                        handler.emit_err(CompileError::ConfigurablesCannotBeShadowed {
341                            shadowing_source: ShadowingSource::LetVar,
342                            name: (&name).into(),
343                            configurable_span: configurable_ident.span(),
344                        });
345                    }
346                    // constant shadowing a constant sequentially
347                    (
348                        constant_ident,
349                        ConstantDeclaration(decl_id),
350                        is_imported_constant,
351                        is_alias,
352                        ConstantDeclaration { .. },
353                        ConstShadowingMode::Sequential,
354                        _,
355                    ) => {
356                        handler.emit_err(CompileError::ConstantsCannotBeShadowed {
357                            shadowing_source: ShadowingSource::Const,
358                            name: (&name).into(),
359                            constant_span: constant_ident.span(),
360                            constant_decl_span: if is_imported_constant {
361                                parsed_decl_engine.get(decl_id).span.clone()
362                            } else {
363                                Span::dummy()
364                            },
365                            is_alias,
366                        });
367                    }
368                    // constant shadowing a configurable sequentially
369                    (
370                        configurable_ident,
371                        ConfigurableDeclaration(_),
372                        _,
373                        _,
374                        ConstantDeclaration { .. },
375                        ConstShadowingMode::Sequential,
376                        _,
377                    ) => {
378                        handler.emit_err(CompileError::ConfigurablesCannotBeShadowed {
379                            shadowing_source: ShadowingSource::Const,
380                            name: (&name).into(),
381                            configurable_span: configurable_ident.span(),
382                        });
383                    }
384                    // constant shadowing a variable
385                    (_, VariableDeclaration(decl_id), _, _, ConstantDeclaration { .. }, _, _) => {
386                        handler.emit_err(CompileError::ConstantShadowsVariable {
387                            name: (&name).into(),
388                            variable_span: parsed_decl_engine.get(decl_id).name.span(),
389                        });
390                    }
391                    // constant shadowing a constant item-style (outside of a function body)
392                    (
393                        constant_ident,
394                        ConstantDeclaration { .. },
395                        _,
396                        _,
397                        ConstantDeclaration { .. },
398                        ConstShadowingMode::ItemStyle,
399                        _,
400                    ) => {
401                        handler.emit_err(CompileError::ConstantDuplicatesConstantOrConfigurable {
402                            existing_constant_or_configurable: "Constant",
403                            new_constant_or_configurable: "Constant",
404                            name: (&name).into(),
405                            existing_span: constant_ident.span(),
406                        });
407                    }
408                    // constant shadowing a configurable item-style (outside of a function body)
409                    (
410                        configurable_ident,
411                        ConfigurableDeclaration { .. },
412                        _,
413                        _,
414                        ConstantDeclaration { .. },
415                        ConstShadowingMode::ItemStyle,
416                        _,
417                    ) => {
418                        handler.emit_err(CompileError::ConstantDuplicatesConstantOrConfigurable {
419                            existing_constant_or_configurable: "Configurable",
420                            new_constant_or_configurable: "Constant",
421                            name: (&name).into(),
422                            existing_span: configurable_ident.span(),
423                        });
424                    }
425                    // configurable shadowing a constant item-style (outside of a function body)
426                    (
427                        constant_ident,
428                        ConstantDeclaration { .. },
429                        _,
430                        _,
431                        ConfigurableDeclaration { .. },
432                        ConstShadowingMode::ItemStyle,
433                        _,
434                    ) => {
435                        handler.emit_err(CompileError::ConstantDuplicatesConstantOrConfigurable {
436                            existing_constant_or_configurable: "Constant",
437                            new_constant_or_configurable: "Configurable",
438                            name: (&name).into(),
439                            existing_span: constant_ident.span(),
440                        });
441                    }
442                    // type or type alias shadowing another type or type alias
443                    // trait/abi shadowing another trait/abi
444                    // type or type alias shadowing a trait/abi, or vice versa
445                    (
446                        _,
447                        StructDeclaration { .. }
448                        | EnumDeclaration { .. }
449                        | TypeAliasDeclaration { .. }
450                        | TraitDeclaration { .. }
451                        | AbiDeclaration { .. },
452                        _,
453                        _,
454                        StructDeclaration { .. }
455                        | EnumDeclaration { .. }
456                        | TypeAliasDeclaration { .. }
457                        | TraitDeclaration { .. }
458                        | AbiDeclaration { .. },
459                        _,
460                        _,
461                    ) => {
462                        handler.emit_err(CompileError::MultipleDefinitionsOfName {
463                            name: name.clone(),
464                            span: name.span(),
465                        });
466                    }
467                    _ => {}
468                }
469            };
470
471        let append_shadowing_error_typed =
472            |ident: &Ident,
473             decl: &ty::TyDecl,
474             is_use: bool,
475             is_alias: bool,
476             item: &ty::TyDecl,
477             const_shadowing_mode: ConstShadowingMode| {
478                use ty::TyDecl::*;
479                match (
480                    ident,
481                    decl,
482                    is_use,
483                    is_alias,
484                    &item,
485                    const_shadowing_mode,
486                    generic_shadowing_mode,
487                ) {
488                    // A general remark for using the `ShadowingSource::LetVar`.
489                    // If the shadowing is detected at this stage, the variable is for
490                    // sure a local variable, because in the case of pattern matching
491                    // struct field variables, the error is already reported and
492                    // the compilation do not proceed to the point of inserting
493                    // the pattern variable into the items.
494
495                    // variable shadowing a constant
496                    (
497                        constant_ident,
498                        ConstantDecl(constant_decl),
499                        is_imported_constant,
500                        is_alias,
501                        VariableDecl { .. },
502                        _,
503                        _,
504                    ) => {
505                        handler.emit_err(CompileError::ConstantsCannotBeShadowed {
506                            shadowing_source: ShadowingSource::LetVar,
507                            name: (&name).into(),
508                            constant_span: constant_ident.span(),
509                            constant_decl_span: if is_imported_constant {
510                                decl_engine.get(&constant_decl.decl_id).span.clone()
511                            } else {
512                                Span::dummy()
513                            },
514                            is_alias,
515                        });
516                    }
517                    // variable shadowing a configurable
518                    (configurable_ident, ConfigurableDecl(_), _, _, VariableDecl { .. }, _, _) => {
519                        handler.emit_err(CompileError::ConfigurablesCannotBeShadowed {
520                            shadowing_source: ShadowingSource::LetVar,
521                            name: (&name).into(),
522                            configurable_span: configurable_ident.span(),
523                        });
524                    }
525                    // constant shadowing a constant sequentially
526                    (
527                        constant_ident,
528                        ConstantDecl(constant_decl),
529                        is_imported_constant,
530                        is_alias,
531                        ConstantDecl { .. },
532                        ConstShadowingMode::Sequential,
533                        _,
534                    ) => {
535                        handler.emit_err(CompileError::ConstantsCannotBeShadowed {
536                            shadowing_source: ShadowingSource::Const,
537                            name: (&name).into(),
538                            constant_span: constant_ident.span(),
539                            constant_decl_span: if is_imported_constant {
540                                decl_engine.get(&constant_decl.decl_id).span.clone()
541                            } else {
542                                Span::dummy()
543                            },
544                            is_alias,
545                        });
546                    }
547                    // constant shadowing a configurable sequentially
548                    (
549                        configurable_ident,
550                        ConfigurableDecl(_),
551                        _,
552                        _,
553                        ConstantDecl { .. },
554                        ConstShadowingMode::Sequential,
555                        _,
556                    ) => {
557                        handler.emit_err(CompileError::ConfigurablesCannotBeShadowed {
558                            shadowing_source: ShadowingSource::Const,
559                            name: (&name).into(),
560                            configurable_span: configurable_ident.span(),
561                        });
562                    }
563                    // constant shadowing a variable
564                    (_, VariableDecl(variable_decl), _, _, ConstantDecl { .. }, _, _) => {
565                        handler.emit_err(CompileError::ConstantShadowsVariable {
566                            name: (&name).into(),
567                            variable_span: variable_decl.name.span(),
568                        });
569                    }
570                    // constant shadowing a constant item-style (outside of a function body)
571                    (
572                        constant_ident,
573                        ConstantDecl { .. },
574                        _,
575                        _,
576                        ConstantDecl { .. },
577                        ConstShadowingMode::ItemStyle,
578                        _,
579                    ) => {
580                        handler.emit_err(CompileError::ConstantDuplicatesConstantOrConfigurable {
581                            existing_constant_or_configurable: "Constant",
582                            new_constant_or_configurable: "Constant",
583                            name: (&name).into(),
584                            existing_span: constant_ident.span(),
585                        });
586                    }
587                    // constant shadowing a configurable item-style (outside of a function body)
588                    (
589                        configurable_ident,
590                        ConfigurableDecl { .. },
591                        _,
592                        _,
593                        ConstantDecl { .. },
594                        ConstShadowingMode::ItemStyle,
595                        _,
596                    ) => {
597                        handler.emit_err(CompileError::ConstantDuplicatesConstantOrConfigurable {
598                            existing_constant_or_configurable: "Configurable",
599                            new_constant_or_configurable: "Constant",
600                            name: (&name).into(),
601                            existing_span: configurable_ident.span(),
602                        });
603                    }
604                    // configurable shadowing a constant item-style (outside of a function body)
605                    (
606                        constant_ident,
607                        ConstantDecl { .. },
608                        _,
609                        _,
610                        ConfigurableDecl { .. },
611                        ConstShadowingMode::ItemStyle,
612                        _,
613                    ) => {
614                        handler.emit_err(CompileError::ConstantDuplicatesConstantOrConfigurable {
615                            existing_constant_or_configurable: "Constant",
616                            new_constant_or_configurable: "Configurable",
617                            name: (&name).into(),
618                            existing_span: constant_ident.span(),
619                        });
620                    }
621                    // type or type alias shadowing another type or type alias
622                    // trait/abi shadowing another trait/abi
623                    // type or type alias shadowing a trait/abi, or vice versa
624                    (
625                        _,
626                        StructDecl { .. }
627                        | EnumDecl { .. }
628                        | TypeAliasDecl { .. }
629                        | TraitDecl { .. }
630                        | AbiDecl { .. },
631                        _,
632                        _,
633                        StructDecl { .. }
634                        | EnumDecl { .. }
635                        | TypeAliasDecl { .. }
636                        | TraitDecl { .. }
637                        | AbiDecl { .. },
638                        _,
639                        _,
640                    ) => {
641                        handler.emit_err(CompileError::MultipleDefinitionsOfName {
642                            name: name.clone(),
643                            span: name.span(),
644                        });
645                    }
646                    // generic parameter shadowing another generic parameter
647                    (
648                        _,
649                        GenericTypeForFunctionScope { .. },
650                        _,
651                        _,
652                        GenericTypeForFunctionScope { .. },
653                        _,
654                        GenericShadowingMode::Disallow,
655                    ) => {
656                        handler.emit_err(CompileError::GenericShadowsGeneric {
657                            name: (&name).into(),
658                        });
659                    }
660                    _ => {}
661                }
662            };
663
664        let append_shadowing_error =
665            |ident: &Ident,
666             decl: &ResolvedDeclaration,
667             is_use: bool,
668             is_alias: bool,
669             item: &ResolvedDeclaration,
670             const_shadowing_mode: ConstShadowingMode| {
671                if const_shadowing_mode == ConstShadowingMode::Allow {
672                    return;
673                }
674                match (decl, item) {
675                    // TODO: Do not handle any shadowing errors while handling parsed declarations yet,
676                    // or else we will emit errors in a different order from the source code order.
677                    // Update this once the full AST resolving pass is in.
678                    (ResolvedDeclaration::Typed(_decl), ResolvedDeclaration::Parsed(_item)) => {}
679                    (ResolvedDeclaration::Parsed(_decl), ResolvedDeclaration::Parsed(_item)) => {}
680                    (ResolvedDeclaration::Typed(decl), ResolvedDeclaration::Typed(item)) => {
681                        append_shadowing_error_typed(
682                            ident,
683                            decl,
684                            is_use,
685                            is_alias,
686                            item,
687                            const_shadowing_mode,
688                        )
689                    }
690                    _ => unreachable!(),
691                }
692            };
693
694        let _ = module.walk_scope_chain_early_return(|lexical_scope| {
695            if let Some((ident, decl)) = lexical_scope.items.symbols.get_key_value(&name) {
696                append_shadowing_error(
697                    ident,
698                    decl,
699                    false,
700                    false,
701                    &item.clone(),
702                    const_shadowing_mode,
703                );
704            }
705
706            if let Some((ident, (imported_ident, _, decl, _))) =
707                lexical_scope.items.use_item_synonyms.get_key_value(&name)
708            {
709                append_shadowing_error(
710                    ident,
711                    decl,
712                    true,
713                    imported_ident.is_some(),
714                    &item,
715                    const_shadowing_mode,
716                );
717            }
718            Ok(None::<()>)
719        });
720
721        if collecting_unifications {
722            module
723                .current_items_mut()
724                .symbols_unique_while_collecting_unifications
725                .write()
726                .insert(name.clone().into(), item.clone());
727        }
728
729        module.current_items_mut().symbols.insert(name, item);
730
731        Ok(())
732    }
733
734    // Add a new binding into use_glob_synonyms. The symbol may already be bound by an earlier
735    // insertion, in which case the new binding is added as well so that multiple bindings exist.
736    //
737    // There are a few edge cases were a new binding will replace an old binding. These edge cases
738    // are a consequence of the prelude reexports not being implemented properly. See comments in
739    // the code for details.
740    pub(crate) fn insert_glob_use_symbol(
741        &mut self,
742        engines: &Engines,
743        symbol: Ident,
744        src_path: ModulePathBuf,
745        decl: &ResolvedDeclaration,
746        visibility: Visibility,
747    ) {
748        if let Some(cur_decls) = self.use_glob_synonyms.get_mut(&symbol) {
749            // Name already bound. Check if the decl is already imported
750            let ctx = PartialEqWithEnginesContext::new(engines);
751            match cur_decls
752                .iter()
753                .position(|(_cur_path, cur_decl, _cur_visibility)| cur_decl.eq(decl, &ctx))
754            {
755                Some(index) if matches!(visibility, Visibility::Public) => {
756                    // The name is already bound to this decl. If the new symbol is more visible
757                    // than the old one, then replace the old one.
758                    cur_decls[index] = (src_path.to_vec(), decl.clone(), visibility);
759                }
760                Some(_) => {
761                    // Same binding as the existing one. Do nothing.
762                }
763                None => {
764                    // New decl for this name. Add it to the end
765                    cur_decls.push((src_path.to_vec(), decl.clone(), visibility));
766                }
767            }
768        } else {
769            let new_vec = vec![(src_path.to_vec(), decl.clone(), visibility)];
770            self.use_glob_synonyms.insert(symbol, new_vec);
771        }
772    }
773
774    pub(crate) fn check_symbol(&self, name: &Ident) -> Result<ResolvedDeclaration, CompileError> {
775        self.symbols
776            .get(name)
777            .cloned()
778            .ok_or_else(|| CompileError::SymbolNotFound {
779                name: name.clone(),
780                span: name.span(),
781            })
782    }
783
784    pub(crate) fn check_symbols_unique_while_collecting_unifications(
785        &self,
786        name: &Ident,
787    ) -> Result<ResolvedDeclaration, CompileError> {
788        self.symbols_unique_while_collecting_unifications
789            .read()
790            .get(&name.into())
791            .cloned()
792            .ok_or_else(|| CompileError::SymbolNotFound {
793                name: name.clone(),
794                span: name.span(),
795            })
796    }
797
798    pub(crate) fn clear_symbols_unique_while_collecting_unifications(&self) {
799        self.symbols_unique_while_collecting_unifications
800            .write()
801            .clear();
802    }
803
804    pub(crate) fn has_storage_declared(&self) -> bool {
805        self.declared_storage.is_some()
806    }
807
808    pub fn get_declared_storage(&self, decl_engine: &DeclEngine) -> Option<TyStorageDecl> {
809        self.declared_storage
810            .as_ref()
811            .map(|decl_ref| (*decl_engine.get_storage(decl_ref)).clone())
812    }
813
814    pub(crate) fn get_storage_field_descriptors(
815        &self,
816        handler: &Handler,
817        decl_engine: &DeclEngine,
818    ) -> Result<Vec<ty::TyStorageField>, ErrorEmitted> {
819        match self.get_declared_storage(decl_engine) {
820            Some(storage) => Ok(storage.fields.clone()),
821            None => {
822                let msg = "unknown source location";
823                let span = Span::new(msg.into(), 0, msg.len(), None).unwrap();
824                Err(handler.emit_err(CompileError::NoDeclaredStorage { span }))
825            }
826        }
827    }
828}
829
830pub(super) fn get_path_for_decl(
831    path: &[sway_types::BaseIdent],
832    decl: &ResolvedDeclaration,
833    engines: &Engines,
834    package_name: &Ident,
835) -> Vec<String> {
836    // Do not report the package name as part of the error if the path is in the current package.
837    let skip_package_name = path[0] == *package_name;
838    let mut path_names = path
839        .iter()
840        .skip(if skip_package_name { 1 } else { 0 })
841        .map(|x| x.to_string())
842        .collect::<Vec<_>>();
843    match decl {
844        ResolvedDeclaration::Parsed(decl) => {
845            if let Declaration::EnumVariantDeclaration(decl) = decl {
846                let enum_decl = engines.pe().get_enum(&decl.enum_ref);
847                path_names.push(enum_decl.name().to_string())
848            };
849        }
850        ResolvedDeclaration::Typed(decl) => {
851            if let TyDecl::EnumVariantDecl(ty::EnumVariantDecl { enum_ref, .. }) = decl {
852                path_names.push(enum_ref.name().to_string())
853            };
854        }
855    }
856    path_names
857}