From 2a98742bf7e4086a779ceecb2bbd7e72499b39a2 Mon Sep 17 00:00:00 2001 From: jjcnn <38888011+jjcnn@users.noreply.github.com> Date: Wed, 1 May 2024 03:13:12 +0200 Subject: [PATCH] Refactor: Move import name resolution to Root (#5916) ## Description Fixes #5913 . Name resolution for imports and top-level items in module currently happens at the module level, in part by traversing the submodules of the current module. This PR moves name resolution to the root of the module structure. This refactoring is needed to enable fixes to the following issues: - #5713 : The resolved type declaration must be understood in the context of the declaring module rather than in the context of the importing module, which means that name resolution must happen across the module structure. - #5498 : The modules from which items are imported are currently introduced as submodules to the importing module (in addition to their absolute location in the module hierarchy). To remove those submodules the name resolution algorithm needs access to the full module hierarchy, which it can get by having access to the root of the hierarchy. ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [x] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [ ] If my change requires substantial documentation changes, I have [requested support from the DevRel team](https://github.com/FuelLabs/devrel-requests/issues/new/choose) - [x] I have added tests that prove my fix is effective or that my feature works. - [x] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers. --------- Co-authored-by: IGI-111 Co-authored-by: Joshua Batty --- .../namespace/lexical_scope.rs | 2 +- .../src/semantic_analysis/namespace/module.rs | 365 +---------------- .../semantic_analysis/namespace/namespace.rs | 7 +- .../src/semantic_analysis/namespace/root.rs | 379 +++++++++++++++++- .../semantic_analysis/type_check_context.rs | 23 +- 5 files changed, 393 insertions(+), 383 deletions(-) diff --git a/sway-core/src/semantic_analysis/namespace/lexical_scope.rs b/sway-core/src/semantic_analysis/namespace/lexical_scope.rs index eaf5e4093c2..e673c3b9284 100644 --- a/sway-core/src/semantic_analysis/namespace/lexical_scope.rs +++ b/sway-core/src/semantic_analysis/namespace/lexical_scope.rs @@ -11,7 +11,7 @@ use crate::{ type_system::*, }; -use super::{module::ResolvedDeclaration, TraitMap}; +use super::{root::ResolvedDeclaration, TraitMap}; use sway_error::{ error::{CompileError, StructFieldUsageContext}, diff --git a/sway-core/src/semantic_analysis/namespace/module.rs b/sway-core/src/semantic_analysis/namespace/module.rs index 16cad9931e8..0b84279159f 100644 --- a/sway-core/src/semantic_analysis/namespace/module.rs +++ b/sway-core/src/semantic_analysis/namespace/module.rs @@ -1,20 +1,15 @@ use crate::{ - decl_engine::DeclRef, engine_threading::Engines, - language::{ - parsed::*, - ty::{self, TyTraitItem}, - CallPath, Visibility, - }, + language::{parsed::*, ty, Visibility}, semantic_analysis::*, transform::to_parsed_lang, - Ident, Namespace, TypeId, TypeInfo, + Ident, Namespace, }; use super::{ lexical_scope::{Items, LexicalScope, SymbolMap}, root::Root, - LexicalScopeId, ModuleName, ModulePath, ModulePathBuf, ResolvedTraitImplItem, + LexicalScopeId, ModuleName, ModulePath, ModulePathBuf, }; use sway_ast::ItemConst; @@ -23,20 +18,6 @@ use sway_error::{error::CompileError, handler::ErrorEmitted}; use sway_parse::{lex, Parser}; use sway_types::{span::Span, Spanned}; -pub enum ResolvedDeclaration { - Parsed(Declaration), - Typed(ty::TyDecl), -} - -impl ResolvedDeclaration { - pub fn expect_typed(self) -> ty::TyDecl { - match self { - ResolvedDeclaration::Parsed(_) => panic!(), - ResolvedDeclaration::Typed(ty_decl) => ty_decl, - } - } -} - /// A single `Module` within a Sway project. /// /// A `Module` is most commonly associated with an individual file of Sway code, e.g. a top-level @@ -336,346 +317,6 @@ impl Module { let parent_scope_id = self.current_lexical_scope().parent; self.current_lexical_scope_id = parent_scope_id.unwrap_or(0); } - - /// Resolve a symbol that is potentially prefixed with some path, e.g. `foo::bar::symbol`. - /// - /// This is short-hand for concatenating the `mod_path` with the `call_path`'s prefixes and - /// then calling `resolve_symbol` with the resulting path and call_path's suffix. - pub(crate) fn resolve_call_path( - &self, - handler: &Handler, - engines: &Engines, - mod_path: &ModulePath, - call_path: &CallPath, - self_type: Option, - ) -> Result { - let (decl, _) = - self.resolve_call_path_and_mod_path(handler, engines, mod_path, call_path, self_type)?; - Ok(decl) - } - - pub(crate) fn resolve_call_path_and_mod_path( - &self, - handler: &Handler, - engines: &Engines, - mod_path: &ModulePath, - call_path: &CallPath, - self_type: Option, - ) -> Result<(ResolvedDeclaration, Vec), ErrorEmitted> { - let symbol_path: Vec<_> = mod_path - .iter() - .chain(&call_path.prefixes) - .cloned() - .collect(); - self.resolve_symbol_and_mod_path( - handler, - engines, - &symbol_path, - &call_path.suffix, - self_type, - ) - } - - pub(crate) fn resolve_call_path_and_root_type_id( - &self, - handler: &Handler, - engines: &Engines, - root_type_id: TypeId, - mut as_trait: Option, - call_path: &CallPath, - self_type: Option, - ) -> Result { - // This block tries to resolve associated types - let mut decl_opt = None; - let mut type_id_opt = Some(root_type_id); - for ident in call_path.prefixes.iter() { - if let Some(type_id) = type_id_opt { - type_id_opt = None; - decl_opt = Some(self.resolve_associated_type_from_type_id( - handler, - engines, - ident, - type_id, - as_trait.clone(), - self_type, - )?); - as_trait = None; - } else if let Some(decl) = decl_opt { - decl_opt = Some(self.resolve_associated_type( - handler, - engines, - ident, - decl, - as_trait.clone(), - self_type, - )?); - as_trait = None; - } - } - if let Some(type_id) = type_id_opt { - let decl = self.resolve_associated_type_from_type_id( - handler, - engines, - &call_path.suffix, - type_id, - as_trait, - self_type, - )?; - return Ok(decl); - } - if let Some(decl) = decl_opt { - let decl = self.resolve_associated_item( - handler, - engines, - &call_path.suffix, - decl, - as_trait, - self_type, - )?; - Ok(decl) - } else { - Err(handler.emit_err(CompileError::Internal("Unexpected error", call_path.span()))) - } - } - - /// Given a path to a module and the identifier of a symbol within that module, resolve its - /// declaration. - /// - /// If the symbol is within the given module's namespace via import, we recursively traverse - /// imports until we find the original declaration. - pub(crate) fn resolve_symbol( - &self, - handler: &Handler, - engines: &Engines, - mod_path: &ModulePath, - symbol: &Ident, - self_type: Option, - ) -> Result { - let (decl, _) = - self.resolve_symbol_and_mod_path(handler, engines, mod_path, symbol, self_type)?; - Ok(decl) - } - - fn resolve_symbol_and_mod_path( - &self, - handler: &Handler, - engines: &Engines, - mod_path: &ModulePath, - symbol: &Ident, - self_type: Option, - ) -> Result<(ResolvedDeclaration, Vec), ErrorEmitted> { - // This block tries to resolve associated types - let mut module = self; - let mut current_mod_path = vec![]; - let mut decl_opt = None; - for ident in mod_path.iter() { - if let Some(decl) = decl_opt { - decl_opt = Some( - self.resolve_associated_type(handler, engines, ident, decl, None, self_type)?, - ); - } else { - match module.submodules.get(ident.as_str()) { - Some(ns) => { - module = ns; - current_mod_path.push(ident.clone()); - } - None => { - decl_opt = Some(self.resolve_symbol_helper( - handler, - engines, - ¤t_mod_path, - ident, - module, - self_type, - )?); - } - } - } - } - if let Some(decl) = decl_opt { - let decl = - self.resolve_associated_item(handler, engines, symbol, decl, None, self_type)?; - return Ok((decl, current_mod_path)); - } - - self.lookup_submodule(handler, engines, mod_path) - .and_then(|module| { - let decl = self - .resolve_symbol_helper(handler, engines, mod_path, symbol, module, self_type)?; - Ok((decl, mod_path.to_vec())) - }) - } - - fn resolve_associated_type( - &self, - handler: &Handler, - engines: &Engines, - symbol: &Ident, - decl: ResolvedDeclaration, - as_trait: Option, - self_type: Option, - ) -> Result { - let type_info = self.decl_to_type_info(handler, engines, symbol, decl)?; - - self.resolve_associated_type_from_type_id( - handler, - engines, - symbol, - engines - .te() - .insert(engines, type_info, symbol.span().source_id()), - as_trait, - self_type, - ) - } - - fn resolve_associated_item( - &self, - handler: &Handler, - engines: &Engines, - symbol: &Ident, - decl: ResolvedDeclaration, - as_trait: Option, - self_type: Option, - ) -> Result { - let type_info = self.decl_to_type_info(handler, engines, symbol, decl)?; - - self.resolve_associated_item_from_type_id( - handler, - engines, - symbol, - engines - .te() - .insert(engines, type_info, symbol.span().source_id()), - as_trait, - self_type, - ) - } - - fn decl_to_type_info( - &self, - handler: &Handler, - engines: &Engines, - symbol: &Ident, - decl: ResolvedDeclaration, - ) -> Result { - match decl { - ResolvedDeclaration::Parsed(_decl) => todo!(), - ResolvedDeclaration::Typed(decl) => Ok(match decl.clone() { - ty::TyDecl::StructDecl(struct_decl) => TypeInfo::Struct(DeclRef::new( - struct_decl.name.clone(), - struct_decl.decl_id, - struct_decl.name.span(), - )), - ty::TyDecl::EnumDecl(enum_decl) => TypeInfo::Enum(DeclRef::new( - enum_decl.name.clone(), - enum_decl.decl_id, - enum_decl.name.span(), - )), - ty::TyDecl::TraitTypeDecl(type_decl) => { - let type_decl = engines.de().get_type(&type_decl.decl_id); - (*engines.te().get(type_decl.ty.clone().unwrap().type_id)).clone() - } - _ => { - return Err(handler.emit_err(CompileError::SymbolNotFound { - name: symbol.clone(), - span: symbol.span(), - })) - } - }), - } - } - - fn resolve_associated_type_from_type_id( - &self, - handler: &Handler, - engines: &Engines, - symbol: &Ident, - type_id: TypeId, - as_trait: Option, - self_type: Option, - ) -> Result { - let item_decl = self.resolve_associated_item_from_type_id( - handler, engines, symbol, type_id, as_trait, self_type, - )?; - Ok(item_decl) - } - - fn resolve_associated_item_from_type_id( - &self, - handler: &Handler, - engines: &Engines, - symbol: &Ident, - type_id: TypeId, - as_trait: Option, - self_type: Option, - ) -> Result { - let type_id = if engines.te().get(type_id).is_self_type() { - if let Some(self_type) = self_type { - self_type - } else { - return Err(handler.emit_err(CompileError::Internal( - "Self type not provided.", - symbol.span(), - ))); - } - } else { - type_id - }; - let item_ref = self - .current_items() - .implemented_traits - .get_trait_item_for_type(handler, engines, symbol, type_id, as_trait)?; - match item_ref { - ResolvedTraitImplItem::Parsed(_item) => todo!(), - ResolvedTraitImplItem::Typed(item) => match item { - TyTraitItem::Fn(fn_ref) => Ok(ResolvedDeclaration::Typed(fn_ref.into())), - TyTraitItem::Constant(const_ref) => { - Ok(ResolvedDeclaration::Typed(const_ref.into())) - } - TyTraitItem::Type(type_ref) => Ok(ResolvedDeclaration::Typed(type_ref.into())), - }, - } - } - - fn resolve_symbol_helper( - &self, - handler: &Handler, - engines: &Engines, - mod_path: &ModulePath, - symbol: &Ident, - module: &Module, - self_type: Option, - ) -> Result { - let true_symbol = self - .lookup_submodule(handler, engines, mod_path)? - .current_items() - .use_aliases - .get(symbol.as_str()) - .unwrap_or(symbol); - // Check locally declared items. Any name clash with imports will have already been reported as an error. - if let Some(decl) = module.current_items().symbols.get(true_symbol) { - return Ok(ResolvedDeclaration::Typed(decl.clone())); - } - // Check item imports - if let Some((_, decl @ ty::TyDecl::EnumVariantDecl { .. })) = - module.current_items().use_item_synonyms.get(symbol) - { - return Ok(ResolvedDeclaration::Typed(decl.clone())); - } - if let Some((src_path, _)) = module.current_items().use_item_synonyms.get(symbol) { - return self.resolve_symbol(handler, engines, src_path, true_symbol, self_type); - } - // Check glob imports - if let Some((_, decl)) = module.current_items().use_glob_synonyms.get(symbol) { - return Ok(ResolvedDeclaration::Typed(decl.clone())); - } - // Symbol not found - Err(handler.emit_err(CompileError::SymbolNotFound { - name: symbol.clone(), - span: symbol.span(), - })) - } } impl From for Module { diff --git a/sway-core/src/semantic_analysis/namespace/namespace.rs b/sway-core/src/semantic_analysis/namespace/namespace.rs index beab3f65a71..37896c8b3b2 100644 --- a/sway-core/src/semantic_analysis/namespace/namespace.rs +++ b/sway-core/src/semantic_analysis/namespace/namespace.rs @@ -4,8 +4,8 @@ use crate::{ }; use super::{ - module::{Module, ResolvedDeclaration}, - root::Root, + module::Module, + root::{ResolvedDeclaration, Root}, submodule_namespace::SubmoduleNamespace, trait_map::ResolvedTraitImplItem, ModulePath, ModulePathBuf, @@ -203,7 +203,6 @@ impl Namespace { self_type: Option, ) -> Result { self.root - .module .resolve_symbol(handler, engines, mod_path, symbol, self_type) } @@ -216,7 +215,6 @@ impl Namespace { self_type: Option, ) -> Result { self.root - .module .resolve_symbol(handler, engines, &self.mod_path, symbol, self_type) } @@ -253,7 +251,6 @@ impl Namespace { self_type: Option, ) -> Result { self.root - .module .resolve_call_path(handler, engines, &self.mod_path, call_path, self_type) } diff --git a/sway-core/src/semantic_analysis/namespace/root.rs b/sway-core/src/semantic_analysis/namespace/root.rs index b02835db5d8..7f5744a44df 100644 --- a/sway-core/src/semantic_analysis/namespace/root.rs +++ b/sway-core/src/semantic_analysis/namespace/root.rs @@ -1,9 +1,16 @@ -use super::{module::Module, namespace::Namespace, trait_map::TraitMap, Ident}; +use super::{ + module::Module, namespace::Namespace, trait_map::TraitMap, Ident, ResolvedTraitImplItem, +}; use crate::{ decl_engine::DeclRef, engine_threading::*, - language::ty::{self, TyDecl}, + language::{ + parsed::*, + ty::{self, TyDecl, TyTraitItem}, + CallPath, + }, namespace::ModulePath, + TypeId, TypeInfo, }; use sway_error::{ error::CompileError, @@ -12,6 +19,20 @@ use sway_error::{ use sway_types::Spanned; use sway_utils::iter_prefixes; +pub enum ResolvedDeclaration { + Parsed(Declaration), + Typed(ty::TyDecl), +} + +impl ResolvedDeclaration { + pub fn expect_typed(self) -> ty::TyDecl { + match self { + ResolvedDeclaration::Parsed(_) => panic!(), + ResolvedDeclaration::Typed(ty_decl) => ty_decl, + } + } +} + /// The root module, from which all other modules can be accessed. /// /// This is equivalent to the "crate root" of a Rust crate. @@ -26,6 +47,8 @@ pub struct Root { } impl Root { + ////// IMPORT ////// + /// Given a path to a `src` module, create synonyms to every symbol in that module to the given /// `dst` module. /// @@ -460,6 +483,358 @@ impl Root { } Ok(()) } + + ////// NAME RESOLUTION ////// + + /// Resolve a symbol that is potentially prefixed with some path, e.g. `foo::bar::symbol`. + /// + /// This is short-hand for concatenating the `mod_path` with the `call_path`'s prefixes and + /// then calling `resolve_symbol` with the resulting path and call_path's suffix. + pub(crate) fn resolve_call_path( + &self, + handler: &Handler, + engines: &Engines, + mod_path: &ModulePath, + call_path: &CallPath, + self_type: Option, + ) -> Result { + let (decl, _) = + self.resolve_call_path_and_mod_path(handler, engines, mod_path, call_path, self_type)?; + Ok(decl) + } + + pub(crate) fn resolve_call_path_and_mod_path( + &self, + handler: &Handler, + engines: &Engines, + mod_path: &ModulePath, + call_path: &CallPath, + self_type: Option, + ) -> Result<(ResolvedDeclaration, Vec), ErrorEmitted> { + let symbol_path: Vec<_> = mod_path + .iter() + .chain(&call_path.prefixes) + .cloned() + .collect(); + self.resolve_symbol_and_mod_path( + handler, + engines, + &symbol_path, + &call_path.suffix, + self_type, + ) + } + + #[allow(clippy::too_many_arguments)] + pub(crate) fn resolve_call_path_and_root_type_id( + &self, + handler: &Handler, + engines: &Engines, + module: &Module, + root_type_id: TypeId, + mut as_trait: Option, + call_path: &CallPath, + self_type: Option, + ) -> Result { + // This block tries to resolve associated types + let mut decl_opt = None; + let mut type_id_opt = Some(root_type_id); + for ident in call_path.prefixes.iter() { + if let Some(type_id) = type_id_opt { + type_id_opt = None; + decl_opt = Some(self.resolve_associated_type_from_type_id( + handler, + engines, + module, + ident, + type_id, + as_trait.clone(), + self_type, + )?); + as_trait = None; + } else if let Some(decl) = decl_opt { + decl_opt = Some(self.resolve_associated_type( + handler, + engines, + module, + ident, + decl, + as_trait.clone(), + self_type, + )?); + as_trait = None; + } + } + if let Some(type_id) = type_id_opt { + let decl = self.resolve_associated_type_from_type_id( + handler, + engines, + module, + &call_path.suffix, + type_id, + as_trait, + self_type, + )?; + return Ok(decl); + } + if let Some(decl) = decl_opt { + let decl = self.resolve_associated_item( + handler, + engines, + module, + &call_path.suffix, + decl, + as_trait, + self_type, + )?; + Ok(decl) + } else { + Err(handler.emit_err(CompileError::Internal("Unexpected error", call_path.span()))) + } + } + + /// Given a path to a module and the identifier of a symbol within that module, resolve its + /// declaration. + /// + /// If the symbol is within the given module's namespace via import, we recursively traverse + /// imports until we find the original declaration. + pub(crate) fn resolve_symbol( + &self, + handler: &Handler, + engines: &Engines, + mod_path: &ModulePath, + symbol: &Ident, + self_type: Option, + ) -> Result { + let (decl, _) = + self.resolve_symbol_and_mod_path(handler, engines, mod_path, symbol, self_type)?; + Ok(decl) + } + + fn resolve_symbol_and_mod_path( + &self, + handler: &Handler, + engines: &Engines, + mod_path: &ModulePath, + symbol: &Ident, + self_type: Option, + ) -> Result<(ResolvedDeclaration, Vec), ErrorEmitted> { + // This block tries to resolve associated types + let mut module = &self.module; + let mut current_mod_path = vec![]; + let mut decl_opt = None; + for ident in mod_path.iter() { + if let Some(decl) = decl_opt { + decl_opt = Some(self.resolve_associated_type( + handler, engines, module, ident, decl, None, self_type, + )?); + } else { + match module.submodules.get(ident.as_str()) { + Some(ns) => { + module = ns; + current_mod_path.push(ident.clone()); + } + None => { + decl_opt = Some( + self.resolve_symbol_helper(handler, engines, ident, module, self_type)?, + ); + } + } + } + } + if let Some(decl) = decl_opt { + let decl = self + .resolve_associated_item(handler, engines, module, symbol, decl, None, self_type)?; + return Ok((decl, current_mod_path)); + } + + self.module + .lookup_submodule(handler, engines, mod_path) + .and_then(|module| { + let decl = + self.resolve_symbol_helper(handler, engines, symbol, module, self_type)?; + Ok((decl, mod_path.to_vec())) + }) + } + + #[allow(clippy::too_many_arguments)] + fn resolve_associated_type( + &self, + handler: &Handler, + engines: &Engines, + module: &Module, + symbol: &Ident, + decl: ResolvedDeclaration, + as_trait: Option, + self_type: Option, + ) -> Result { + let type_info = self.decl_to_type_info(handler, engines, symbol, decl)?; + + self.resolve_associated_type_from_type_id( + handler, + engines, + module, + symbol, + engines + .te() + .insert(engines, type_info, symbol.span().source_id()), + as_trait, + self_type, + ) + } + + #[allow(clippy::too_many_arguments)] + fn resolve_associated_item( + &self, + handler: &Handler, + engines: &Engines, + module: &Module, + symbol: &Ident, + decl: ResolvedDeclaration, + as_trait: Option, + self_type: Option, + ) -> Result { + let type_info = self.decl_to_type_info(handler, engines, symbol, decl)?; + + self.resolve_associated_item_from_type_id( + handler, + engines, + module, + symbol, + engines + .te() + .insert(engines, type_info, symbol.span().source_id()), + as_trait, + self_type, + ) + } + + fn decl_to_type_info( + &self, + handler: &Handler, + engines: &Engines, + symbol: &Ident, + decl: ResolvedDeclaration, + ) -> Result { + match decl { + ResolvedDeclaration::Parsed(_decl) => todo!(), + ResolvedDeclaration::Typed(decl) => Ok(match decl.clone() { + ty::TyDecl::StructDecl(struct_decl) => TypeInfo::Struct(DeclRef::new( + struct_decl.name.clone(), + struct_decl.decl_id, + struct_decl.name.span(), + )), + ty::TyDecl::EnumDecl(enum_decl) => TypeInfo::Enum(DeclRef::new( + enum_decl.name.clone(), + enum_decl.decl_id, + enum_decl.name.span(), + )), + ty::TyDecl::TraitTypeDecl(type_decl) => { + let type_decl = engines.de().get_type(&type_decl.decl_id); + (*engines.te().get(type_decl.ty.clone().unwrap().type_id)).clone() + } + _ => { + return Err(handler.emit_err(CompileError::SymbolNotFound { + name: symbol.clone(), + span: symbol.span(), + })) + } + }), + } + } + + #[allow(clippy::too_many_arguments)] + fn resolve_associated_type_from_type_id( + &self, + handler: &Handler, + engines: &Engines, + module: &Module, + symbol: &Ident, + type_id: TypeId, + as_trait: Option, + self_type: Option, + ) -> Result { + let item_decl = self.resolve_associated_item_from_type_id( + handler, engines, module, symbol, type_id, as_trait, self_type, + )?; + Ok(item_decl) + } + + #[allow(clippy::too_many_arguments)] + fn resolve_associated_item_from_type_id( + &self, + handler: &Handler, + engines: &Engines, + module: &Module, + symbol: &Ident, + type_id: TypeId, + as_trait: Option, + self_type: Option, + ) -> Result { + let type_id = if engines.te().get(type_id).is_self_type() { + if let Some(self_type) = self_type { + self_type + } else { + return Err(handler.emit_err(CompileError::Internal( + "Self type not provided.", + symbol.span(), + ))); + } + } else { + type_id + }; + let item_ref = module + .current_items() + .implemented_traits + .get_trait_item_for_type(handler, engines, symbol, type_id, as_trait)?; + match item_ref { + ResolvedTraitImplItem::Parsed(_item) => todo!(), + ResolvedTraitImplItem::Typed(item) => match item { + TyTraitItem::Fn(fn_ref) => Ok(ResolvedDeclaration::Typed(fn_ref.into())), + TyTraitItem::Constant(const_ref) => { + Ok(ResolvedDeclaration::Typed(const_ref.into())) + } + TyTraitItem::Type(type_ref) => Ok(ResolvedDeclaration::Typed(type_ref.into())), + }, + } + } + + fn resolve_symbol_helper( + &self, + handler: &Handler, + engines: &Engines, + symbol: &Ident, + module: &Module, + self_type: Option, + ) -> Result { + let true_symbol = module + .current_items() + .use_aliases + .get(symbol.as_str()) + .unwrap_or(symbol); + // Check locally declared items. Any name clash with imports will have already been reported as an error. + if let Some(decl) = module.current_items().symbols.get(true_symbol) { + return Ok(ResolvedDeclaration::Typed(decl.clone())); + } + // Check item imports + if let Some((_, decl @ ty::TyDecl::EnumVariantDecl { .. })) = + module.current_items().use_item_synonyms.get(symbol) + { + return Ok(ResolvedDeclaration::Typed(decl.clone())); + } + if let Some((src_path, _)) = module.current_items().use_item_synonyms.get(symbol) { + return self.resolve_symbol(handler, engines, src_path, true_symbol, self_type); + } + // Check glob imports + if let Some((_, decl)) = module.current_items().use_glob_synonyms.get(symbol) { + return Ok(ResolvedDeclaration::Typed(decl.clone())); + } + // Symbol not found + Err(handler.emit_err(CompileError::SymbolNotFound { + name: symbol.clone(), + span: symbol.span(), + })) + } } impl From for Root { diff --git a/sway-core/src/semantic_analysis/type_check_context.rs b/sway-core/src/semantic_analysis/type_check_context.rs index 6214302541e..b7d71376e01 100644 --- a/sway-core/src/semantic_analysis/type_check_context.rs +++ b/sway-core/src/semantic_analysis/type_check_context.rs @@ -572,10 +572,11 @@ impl<'a> TypeCheckContext<'a> { } => { let type_decl_opt = if let Some(root_type_id) = root_type_id { self.namespace() - .module(engines) + .root .resolve_call_path_and_root_type_id( handler, self.engines, + self.namespace().module(engines), root_type_id, None, &qualified_call_path.clone().to_call_path(handler)?, @@ -779,17 +780,13 @@ impl<'a> TypeCheckContext<'a> { call_path: &CallPath, ) -> Result { let engines = self.engines; - let (decl, mod_path) = self - .namespace() - .root - .module - .resolve_call_path_and_mod_path( - handler, - self.engines, - mod_path, - call_path, - self.self_type, - )?; + let (decl, mod_path) = self.namespace().root.resolve_call_path_and_mod_path( + handler, + self.engines, + mod_path, + call_path, + self.self_type, + )?; let decl = decl.expect_typed(); // In case there is no mod path we don't need to check visibility @@ -887,10 +884,10 @@ impl<'a> TypeCheckContext<'a> { self.namespace() .root - .module .resolve_call_path_and_root_type_id( handler, self.engines, + &self.namespace().root.module, root_type_id, as_trait_opt, &qualified_call_path.call_path,