From 51e8c9d678249caa14196b19f130a21031e5b15d Mon Sep 17 00:00:00 2001 From: jjcnn <38888011+jjcnn@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:32:35 +0100 Subject: [PATCH] Remove `DeRef` and `DeRefMut` implementations in the `namespace` module (#5577) ## Description This PR is the first step of a large refactoring of the `namespace` module. The PR removes the `DeRef` and `DeRefMut` implementations in the `namespace` module, as they make refactoring more difficult to keep track of. This change means that calls to `Root` and `Module` must now explicitly go through `Namespace`, since that is the type that is passed along during typechecking. I'm submitting the PR now because there have been changes to `master` while I've been working on this, and the changes are really difficult to merge, so I want `master` to be relatively stable. Subsequent PRs will: - Eliminate the `dst` parameter from all import functions (the destination is always the current module). - Move all import functions to `Namespace` (they currently reside in `Module` where they aren't needed, and where they require a clone the module path to work). - Move `Namespace::init` to `Root`, and change how it is used (it currently holds a constant declaration of `CONTRACT_ID` for contract modules, and that declaration is cloned into every submodule. The nice way to do this is to declare it in the root module and implicitly import it into each submodule). - Eliminate the `Option` part of `Module::name` (modules are not allowed to be nameless - the option only exists because they root module can in principle be nameless, but it ought to be named based on the package the module structure is in). - Fix the import and name resolution functions so that they don't treat absolute paths as relative (this should fix some of the performance issues we're seeing). - Make `Namespace::root` a reference so that the entire module structure isn't cloned for every submodule (this requires a change in ownership of the root module). - Introduce reexports in the form of `pub use`. This PR is the first step in fixing #5498. ## 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). - [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. --- forc-pkg/src/pkg.rs | 24 +-- sway-core/src/abi_generation/fuel_abi.rs | 2 +- sway-core/src/ir_generation.rs | 8 +- sway-core/src/ir_generation/compile.rs | 4 +- sway-core/src/ir_generation/const_eval.rs | 2 +- sway-core/src/language/call_path.rs | 12 +- sway-core/src/lib.rs | 2 +- .../semantic_analysis/ast_node/code_block.rs | 3 +- .../ast_node/declaration/abi.rs | 2 +- .../ast_node/declaration/auto_impl.rs | 4 +- .../ast_node/declaration/declaration.rs | 2 + .../function/function_parameter.rs | 2 +- .../ast_node/declaration/impl_trait.rs | 2 + .../ast_node/declaration/trait.rs | 2 +- .../ast_node/expression/typed_expression.rs | 26 +-- .../typed_expression/method_application.rs | 5 +- .../typed_expression/struct_instantiation.rs | 5 +- .../src/semantic_analysis/ast_node/mod.rs | 4 +- .../src/semantic_analysis/namespace/module.rs | 138 ++++++++------- .../semantic_analysis/namespace/namespace.rs | 164 +++++++++++------- .../src/semantic_analysis/namespace/root.rs | 13 -- .../semantic_analysis/type_check_context.rs | 102 ++++++----- .../src/type_system/ast_elements/binding.rs | 3 +- .../ast_elements/type_parameter.rs | 14 +- sway-core/src/type_system/id.rs | 2 + .../capabilities/hover/hover_link_contents.rs | 15 +- sway-lsp/src/core/session.rs | 8 +- sway-lsp/src/traverse/typed_tree.rs | 18 +- test/src/ir_generation/mod.rs | 20 ++- 29 files changed, 353 insertions(+), 255 deletions(-) diff --git a/forc-pkg/src/pkg.rs b/forc-pkg/src/pkg.rs index acfef7669bf..ba8823dc01a 100644 --- a/forc-pkg/src/pkg.rs +++ b/forc-pkg/src/pkg.rs @@ -179,7 +179,7 @@ pub struct CompiledPackage { pub program_abi: ProgramABI, pub storage_slots: Vec, pub bytecode: BuiltPackageBytecode, - pub namespace: namespace::Root, + pub root_module: namespace::Module, pub warnings: Vec, pub metrics: PerformanceData, } @@ -1656,18 +1656,18 @@ pub fn dependency_namespace( let _ = namespace.star_import_with_reexports( &Handler::default(), + engines, &[CORE, PRELUDE].map(|s| Ident::new_no_span(s.into())), &[], - engines, true, ); if has_std_dep(graph, node) { let _ = namespace.star_import_with_reexports( &Handler::default(), + engines, &[STD, PRELUDE].map(|s| Ident::new_no_span(s.into())), &[], - engines, true, ); } @@ -1807,7 +1807,7 @@ pub fn compile( let storage_slots = typed_program.storage_slots.clone(); let tree_type = typed_program.kind.tree_type(); - let namespace = typed_program.root.namespace.clone().into(); + let namespace = typed_program.root.namespace.clone(); if handler.has_errors() { return fail(handler); @@ -1932,7 +1932,7 @@ pub fn compile( storage_slots, tree_type, bytecode, - namespace, + root_module: namespace.root_module().clone(), warnings, metrics, }; @@ -2430,9 +2430,9 @@ pub fn build( } if let TreeType::Library = compiled.tree_type { - let mut namespace = namespace::Module::from(compiled.namespace); - namespace.name = Some(Ident::new_no_span(pkg.name.clone())); - lib_namespace_map.insert(node, namespace); + let mut root_module = compiled.root_module; + root_module.name = Some(Ident::new_no_span(pkg.name.clone())); + lib_namespace_map.insert(node, root_module); } source_map.insert_dependency(descriptor.manifest_file.dir()); @@ -2679,9 +2679,9 @@ pub fn check( match programs.typed.as_ref() { Ok(typed_program) => { if let TreeType::Library = typed_program.kind.tree_type() { - let mut namespace = typed_program.root.namespace.clone(); - namespace.name = Some(Ident::new_no_span(pkg.name.clone())); - namespace.span = Some( + let mut module = typed_program.root.namespace.module().clone(); + module.name = Some(Ident::new_no_span(pkg.name.clone())); + module.span = Some( Span::new( manifest.entry_string()?, 0, @@ -2690,7 +2690,7 @@ pub fn check( ) .unwrap(), ); - lib_namespace_map.insert(node, namespace.module().clone()); + lib_namespace_map.insert(node, module); } source_map.insert_dependency(manifest.dir()); diff --git a/sway-core/src/abi_generation/fuel_abi.rs b/sway-core/src/abi_generation/fuel_abi.rs index 5245e987ac1..27916a7c79d 100644 --- a/sway-core/src/abi_generation/fuel_abi.rs +++ b/sway-core/src/abi_generation/fuel_abi.rs @@ -885,7 +885,7 @@ fn call_path_display(ctx: &mut AbiContext, call_path: &CallPath) -> String { for (index, prefix) in call_path.prefixes.iter().enumerate() { let mut skip_prefix = false; if index == 0 { - if let Some(root_name) = ctx.program.root.namespace.name.clone() { + if let Some(root_name) = &ctx.program.root.namespace.module().name { if prefix.as_str() == root_name.as_str() { skip_prefix = true; } diff --git a/sway-core/src/ir_generation.rs b/sway-core/src/ir_generation.rs index ba7fad6a4ab..c56613a239a 100644 --- a/sway-core/src/ir_generation.rs +++ b/sway-core/src/ir_generation.rs @@ -67,7 +67,7 @@ pub fn compile_program<'eng>( engines, &mut ctx, main_function, - &root.namespace, + root.namespace.module(), declarations, &logged_types, &messages_types, @@ -77,7 +77,7 @@ pub fn compile_program<'eng>( engines, &mut ctx, main_function, - &root.namespace, + root.namespace.module(), declarations, &logged_types, &messages_types, @@ -86,7 +86,7 @@ pub fn compile_program<'eng>( ty::TyProgramKind::Contract { abi_entries } => compile::compile_contract( &mut ctx, abi_entries, - &root.namespace, + root.namespace.module(), declarations, &logged_types, &messages_types, @@ -96,7 +96,7 @@ pub fn compile_program<'eng>( ty::TyProgramKind::Library { .. } => compile::compile_library( engines, &mut ctx, - &root.namespace, + root.namespace.module(), declarations, &logged_types, &messages_types, diff --git a/sway-core/src/ir_generation/compile.rs b/sway-core/src/ir_generation/compile.rs index 47ae6b3f7fa..2016f04d881 100644 --- a/sway-core/src/ir_generation/compile.rs +++ b/sway-core/src/ir_generation/compile.rs @@ -205,9 +205,9 @@ pub(crate) fn compile_constants( module: Module, module_ns: &namespace::Module, ) -> Result<(), CompileError> { - for decl_name in module_ns.get_all_declared_symbols() { + for decl_name in module_ns.items().get_all_declared_symbols() { if let Some(ty::TyDecl::ConstantDecl(ty::ConstantDecl { decl_id, .. })) = - module_ns.symbols.get(decl_name) + module_ns.items().symbols.get(decl_name) { let const_decl = engines.de().get_constant(decl_id); let call_path = const_decl.call_path.clone(); diff --git a/sway-core/src/ir_generation/const_eval.rs b/sway-core/src/ir_generation/const_eval.rs index a157da8c085..acc06b846b7 100644 --- a/sway-core/src/ir_generation/const_eval.rs +++ b/sway-core/src/ir_generation/const_eval.rs @@ -124,7 +124,7 @@ pub(crate) fn compile_const_decl( (_, Some(config_val), _) => Ok(Some(config_val)), (None, None, Some(module_ns)) => { // See if we it's a global const and whether we can compile it *now*. - let decl = module_ns.check_symbol(&call_path.suffix); + let decl = module_ns.items().check_symbol(&call_path.suffix); let const_decl = match const_decl { Some(decl) => Some(decl), None => None, diff --git a/sway-core/src/language/call_path.rs b/sway-core/src/language/call_path.rs index 3c109a97b9d..feaf04e5d61 100644 --- a/sway-core/src/language/call_path.rs +++ b/sway-core/src/language/call_path.rs @@ -313,10 +313,10 @@ impl CallPath { let mut is_external = false; let mut is_absolute = false; - if let Some(use_synonym) = namespace.use_synonyms.get(&self.suffix) { + if let Some(use_synonym) = namespace.module().items().use_synonyms.get(&self.suffix) { synonym_prefixes = use_synonym.0.clone(); is_absolute = use_synonym.3; - let submodule = namespace.submodule(&[use_synonym.0[0].clone()]); + let submodule = namespace.module().submodule(&[use_synonym.0[0].clone()]); if let Some(submodule) = submodule { is_external = submodule.is_external; } @@ -325,7 +325,7 @@ impl CallPath { let mut prefixes: Vec = vec![]; if !is_external { - if let Some(pkg_name) = &namespace.root().module.name { + if let Some(pkg_name) = &namespace.root_module().name { prefixes.push(pkg_name.clone()); } @@ -343,7 +343,7 @@ impl CallPath { suffix: self.suffix.clone(), is_absolute: true, } - } else if let Some(m) = namespace.submodule(&[self.prefixes[0].clone()]) { + } else if let Some(m) = namespace.module().submodule(&[self.prefixes[0].clone()]) { // If some prefixes are already present, attempt to complete the path by adding the // package name and the path to the current submodule. // @@ -357,7 +357,7 @@ impl CallPath { } } else { let mut prefixes: Vec = vec![]; - if let Some(pkg_name) = &namespace.root().module.name { + if let Some(pkg_name) = &namespace.root_module().name { prefixes.push(pkg_name.clone()); } for mod_path in namespace.mod_path() { @@ -391,7 +391,7 @@ impl CallPath { let converted = self.to_fullpath(namespace); if let Some(first) = converted.prefixes.first() { - if namespace.root().name == Some(first.clone()) { + if namespace.root_module().name == Some(first.clone()) { return converted.lshift(); } } diff --git a/sway-core/src/lib.rs b/sway-core/src/lib.rs index 42a543f87d5..7b565f6bdcc 100644 --- a/sway-core/src/lib.rs +++ b/sway-core/src/lib.rs @@ -587,7 +587,7 @@ pub fn parsed_to_ast( &mut ctx, &mut md_mgr, module, - &typed_program.root.namespace, + typed_program.root.namespace.module(), ) { handler.emit_err(e); } diff --git a/sway-core/src/semantic_analysis/ast_node/code_block.rs b/sway-core/src/semantic_analysis/ast_node/code_block.rs index 7a604e34e4e..d27ca5eb8ca 100644 --- a/sway-core/src/semantic_analysis/ast_node/code_block.rs +++ b/sway-core/src/semantic_analysis/ast_node/code_block.rs @@ -84,8 +84,7 @@ impl ty::TyCodeBlock { let never_decl_opt = ctx .namespace - .root() - .resolve_symbol( + .resolve_root_symbol( &Handler::default(), engines, &never_mod_path, diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs b/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs index 16632fc2a01..f97c2c50be1 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs @@ -299,7 +299,7 @@ impl ty::TyAbiDecl { all_items.push(TyImplItem::Constant(decl_ref.clone())); let const_shadowing_mode = ctx.const_shadowing_mode(); let generic_shadowing_mode = ctx.generic_shadowing_mode(); - let _ = ctx.namespace.insert_symbol( + let _ = ctx.namespace.module_mut().items_mut().insert_symbol( handler, const_name.clone(), ty::TyDecl::ConstantDecl(ty::ConstantDecl { diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs b/sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs index 2251950b37f..865d49d4f5d 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs @@ -502,7 +502,7 @@ impl<'a, 'b> AutoImplAbiEncodeContext<'a, 'b> { // skip module "core" // Because of ordering, we cannot guarantee auto impl // for structs inside "core" - if matches!(self.ctx.namespace.root().name.as_ref(), Some(x) if x.as_str() == "core") { + if matches!(self.ctx.namespace.root_module_name(), Some(x) if x.as_str() == "core") { return false; } @@ -531,6 +531,8 @@ impl<'a, 'b> AutoImplAbiEncodeContext<'a, 'b> { let handler = Handler::default(); self.ctx .namespace + .module_mut() + .items_mut() .implemented_traits .check_if_trait_constraints_are_satisfied_for_type( &handler, diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs index 0cd3b83b9e3..558579d574b 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs @@ -362,6 +362,8 @@ impl TyDecl { // declarations are not allowed ctx.namespace + .module_mut() + .items_mut() .set_storage_declaration(handler, decl_ref.clone())?; decl_ref.into() } diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs b/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs index a7a9dbf6254..9cc2e048371 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs @@ -105,7 +105,7 @@ impl ty::TyFunctionParameter { pub fn insert_into_namespace(&self, handler: &Handler, ctx: TypeCheckContext) { let const_shadowing_mode = ctx.const_shadowing_mode(); let generic_shadowing_mode = ctx.generic_shadowing_mode(); - let _ = ctx.namespace.insert_symbol( + let _ = ctx.namespace.module_mut().items_mut().insert_symbol( handler, self.name.clone(), ty::TyDecl::VariableDecl(Box::new(ty::TyVariableDecl { diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs b/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs index e65ea4a206f..10f5a2fb9d1 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs @@ -620,6 +620,8 @@ fn type_check_trait_implementation( // Check to see if the type that we are implementing for implements the // supertraits of this trait. ctx.namespace + .module_mut() + .items_mut() .implemented_traits .check_if_trait_constraints_are_satisfied_for_type( handler, diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs b/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs index 8d48cbeab41..bf9a9fcf47e 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs @@ -444,7 +444,7 @@ impl TyTraitDecl { all_items.push(TyImplItem::Constant(decl_ref.clone())); let const_shadowing_mode = ctx.const_shadowing_mode(); let generic_shadowing_mode = ctx.generic_shadowing_mode(); - let _ = ctx.namespace.insert_symbol( + let _ = ctx.namespace.module_mut().items_mut().insert_symbol( handler, const_name.clone(), ty::TyDecl::ConstantDecl(ty::ConstantDecl { diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs index 4dc98f755ca..2f12f975c1b 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -1023,16 +1023,18 @@ impl ty::TyExpression { let decl_engine = ctx.engines.de(); let engines = ctx.engines(); - if !ctx.namespace.has_storage_declared() { + if !ctx.namespace.module().items().has_storage_declared() { return Err(handler.emit_err(CompileError::NoDeclaredStorage { span: span.clone() })); } let storage_fields = ctx .namespace + .module() + .items() .get_storage_field_descriptors(handler, decl_engine)?; // Do all namespace checking here! - let (storage_access, mut access_type) = ctx.namespace.apply_storage_load( + let (storage_access, mut access_type) = ctx.namespace.module().items().apply_storage_load( handler, ctx.engines, ctx.namespace, @@ -1050,7 +1052,7 @@ impl ty::TyExpression { let storage_key_ident = Ident::new_with_override("StorageKey".into(), span.clone()); // Search for the struct declaration with the call path above. - let storage_key_decl_opt = ctx.namespace.root().resolve_symbol( + let storage_key_decl_opt = ctx.namespace.resolve_root_symbol( handler, engines, &storage_key_mod_path, @@ -1254,7 +1256,7 @@ impl ty::TyExpression { path.push(before.inner.clone()); let not_module = { let h = Handler::default(); - ctx.namespace.check_submodule(&h, &path).is_err() + ctx.namespace.module().check_submodule(&h, &path).is_err() }; // Not a module? Not a `Enum::Variant` either? @@ -1373,6 +1375,7 @@ impl ty::TyExpression { is_module = { let call_path_binding = unknown_call_path_binding.clone(); ctx.namespace + .module() .check_submodule( &module_probe_handler, &[ @@ -2014,13 +2017,14 @@ impl ty::TyExpression { } }; let names_vec = names_vec.into_iter().rev().collect::>(); - let (ty_of_field, _ty_of_parent) = ctx.namespace.find_subfield_type( - handler, - ctx.engines(), - ctx.namespace, - &base_name, - &names_vec, - )?; + let (ty_of_field, _ty_of_parent) = + ctx.namespace.module().items().find_subfield_type( + handler, + ctx.engines(), + ctx.namespace, + &base_name, + &names_vec, + )?; // type check the reassignment let ctx = ctx.with_type_annotation(ty_of_field).with_help_text(""); let rhs_span = rhs.span(); diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs index 8833d61cfb0..414dd697688 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs @@ -439,8 +439,7 @@ pub(crate) fn resolve_method_name( .namespace .find_module_path(&call_path_binding.inner.prefixes); ctx.namespace - .root() - .check_submodule(handler, &type_info_prefix)?; + .check_absolute_path_to_submodule(handler, &type_info_prefix)?; // find the method let decl_ref = ctx.find_method_for_type( @@ -464,7 +463,7 @@ pub(crate) fn resolve_method_name( let mut module_path = call_path.prefixes.clone(); if let (Some(root_mod), Some(root_name)) = ( module_path.first().cloned(), - ctx.namespace.root().name.clone(), + ctx.namespace.root_module_name().clone(), ) { if root_mod.as_str() == root_name.as_str() { module_path.remove(0); diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/struct_instantiation.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/struct_instantiation.rs index 7b9914b7af4..1cb4e22fbe2 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/struct_instantiation.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/struct_instantiation.rs @@ -80,8 +80,7 @@ pub(crate) fn struct_instantiation( // find the module that the struct decl is in let type_info_prefix = ctx.namespace.find_module_path(&prefixes); ctx.namespace - .root() - .check_submodule(handler, &type_info_prefix)?; + .check_absolute_path_to_submodule(handler, &type_info_prefix)?; // resolve the type of the struct decl let type_id = ctx @@ -255,6 +254,8 @@ pub(crate) fn struct_instantiation( // but that would be a way too much of suggestions, and moreover, it is also not a design pattern/guideline // that we wish to encourage. namespace + .module() + .items() .get_items_for_type(engines, struct_type_id) .iter() .filter_map(|item| match item { diff --git a/sway-core/src/semantic_analysis/ast_node/mod.rs b/sway-core/src/semantic_analysis/ast_node/mod.rs index 1f9785e1664..449ed4fa1c1 100644 --- a/sway-core/src/semantic_analysis/ast_node/mod.rs +++ b/sway-core/src/semantic_analysis/ast_node/mod.rs @@ -34,7 +34,9 @@ impl ty::TyAstNode { content: match node.content.clone() { AstNodeContent::UseStatement(a) => { let mut is_external = false; - if let Some(submodule) = ctx.namespace.submodule(&[a.call_path[0].clone()]) { + if let Some(submodule) = + ctx.namespace.module().submodule(&[a.call_path[0].clone()]) + { is_external = submodule.is_external; } let path = if is_external || a.is_absolute { diff --git a/sway-core/src/semantic_analysis/namespace/module.rs b/sway-core/src/semantic_analysis/namespace/module.rs index abf2f70e7e4..aac01ab7624 100644 --- a/sway-core/src/semantic_analysis/namespace/module.rs +++ b/sway-core/src/semantic_analysis/namespace/module.rs @@ -228,6 +228,16 @@ impl Module { } } + /// The collection of items declared by this module + pub fn items(&self) -> &Items { + &self.items + } + + /// The mutable collection of items declared by this module + pub fn items_mut(&mut self) -> &mut Items { + &mut self.items + } + /// Given a path to a `src` module, create synonyms to every symbol in that module to the given /// `dst` module. /// @@ -237,31 +247,32 @@ impl Module { pub(crate) fn star_import( &mut self, handler: &Handler, + engines: &Engines, src: &Path, dst: &Path, - engines: &Engines, is_src_absolute: bool, ) -> Result<(), ErrorEmitted> { - self.check_module_privacy(handler, src, dst)?; + self.check_module_privacy(handler, src)?; let decl_engine = engines.de(); - let src_ns = self.check_submodule(handler, src)?; + let src_mod = self.check_submodule(handler, src)?; - let implemented_traits = src_ns.implemented_traits.clone(); + let implemented_traits = src_mod.items().implemented_traits.clone(); let mut symbols_and_decls = vec![]; - for (symbol, decl) in src_ns.symbols.iter() { + for (symbol, decl) in src_mod.items().symbols.iter() { if is_ancestor(src, dst) || decl.visibility(decl_engine).is_public() { symbols_and_decls.push((symbol.clone(), decl.clone())); } } - let dst_ns = &mut self[dst]; - dst_ns + let dst_mod = &mut self[dst]; + dst_mod + .items_mut() .implemented_traits .extend(implemented_traits, engines); for symbol_and_decl in symbols_and_decls { - dst_ns.use_synonyms.insert( + dst_mod.items_mut().use_synonyms.insert( symbol_and_decl.0, ( src.to_vec(), @@ -284,25 +295,26 @@ impl Module { pub fn star_import_with_reexports( &mut self, handler: &Handler, + engines: &Engines, src: &Path, dst: &Path, - engines: &Engines, is_src_absolute: bool, ) -> Result<(), ErrorEmitted> { - self.check_module_privacy(handler, src, dst)?; + self.check_module_privacy(handler, src)?; let decl_engine = engines.de(); - let src_ns = self.check_submodule(handler, src)?; + let src_mod = self.check_submodule(handler, src)?; - let implemented_traits = src_ns.implemented_traits.clone(); - let use_synonyms = src_ns.use_synonyms.clone(); - let mut symbols_and_decls = src_ns + let implemented_traits = src_mod.items().implemented_traits.clone(); + let use_synonyms = src_mod.items().use_synonyms.clone(); + let mut symbols_and_decls = src_mod + .items() .use_synonyms .iter() .map(|(symbol, (_, _, decl, _))| (symbol.clone(), decl.clone())) .collect::>(); - for (symbol, decl) in src_ns.symbols.iter() { + for (symbol, decl) in src_mod.items().symbols.iter() { if is_ancestor(src, dst) || decl.visibility(decl_engine).is_public() { symbols_and_decls.push((symbol.clone(), decl.clone())); } @@ -311,7 +323,7 @@ impl Module { let mut symbols_paths_and_decls = vec![]; for (symbol, (mod_path, _, decl, _)) in use_synonyms { let mut is_external = false; - let submodule = src_ns.submodule(&[mod_path[0].clone()]); + let submodule = src_mod.submodule(&[mod_path[0].clone()]); if let Some(submodule) = submodule { is_external = submodule.is_external }; @@ -326,13 +338,15 @@ impl Module { symbols_paths_and_decls.push((symbol, path, decl)); } - let dst_ns = &mut self[dst]; - dst_ns + let dst_mod = &mut self[dst]; + dst_mod + .items_mut() .implemented_traits .extend(implemented_traits, engines); let mut try_add = |symbol, path, decl: ty::TyDecl| { - dst_ns + dst_mod + .items_mut() .use_synonyms .insert(symbol, (path, GlobImport::Yes, decl, is_src_absolute)); }; @@ -387,13 +401,13 @@ impl Module { alias: Option, is_src_absolute: bool, ) -> Result<(), ErrorEmitted> { - self.check_module_privacy(handler, src, dst)?; + self.check_module_privacy(handler, src)?; let decl_engine = engines.de(); - let src_ns = self.check_submodule(handler, src)?; + let src_mod = self.check_submodule(handler, src)?; let mut impls_to_insert = TraitMap::default(); - match src_ns.symbols.get(item).cloned() { + match src_mod.items().symbols.get(item).cloned() { Some(decl) => { if !decl.visibility(decl_engine).is_public() && !is_ancestor(src, dst) { handler.emit_err(CompileError::ImportPrivateSymbol { @@ -405,7 +419,8 @@ impl Module { // if this is an enum or struct or function, import its implementations if let Ok(type_id) = decl.return_type(&Handler::default(), engines) { impls_to_insert.extend( - src_ns + src_mod + .items() .implemented_traits .filter_by_type_item_import(type_id, engines), engines, @@ -417,19 +432,21 @@ impl Module { // TODO: we only import local impls from the source namespace // this is okay for now but we'll need to device some mechanism to collect all available trait impls impls_to_insert.extend( - src_ns + src_mod + .items() .implemented_traits .filter_by_trait_decl_span(decl_span), engines, ); } // no matter what, import it this way though. - let dst_ns = &mut self[dst]; + let dst_mod = &mut self[dst]; let add_synonym = |name| { - if let Some((_, GlobImport::No, _, _)) = dst_ns.use_synonyms.get(name) { + if let Some((_, GlobImport::No, _, _)) = dst_mod.items().use_synonyms.get(name) + { handler.emit_err(CompileError::ShadowsOtherSymbol { name: name.into() }); } - dst_ns.use_synonyms.insert( + dst_mod.items_mut().use_synonyms.insert( name.clone(), (src.to_vec(), GlobImport::No, decl, is_src_absolute), ); @@ -437,7 +454,8 @@ impl Module { match alias { Some(alias) => { add_synonym(&alias); - dst_ns + dst_mod + .items_mut() .use_aliases .insert(alias.as_str().to_string(), item.clone()); } @@ -452,8 +470,11 @@ impl Module { } }; - let dst_ns = &mut self[dst]; - dst_ns.implemented_traits.extend(impls_to_insert, engines); + let dst_mod = &mut self[dst]; + dst_mod + .items_mut() + .implemented_traits + .extend(impls_to_insert, engines); Ok(()) } @@ -473,12 +494,12 @@ impl Module { alias: Option, is_src_absolute: bool, ) -> Result<(), ErrorEmitted> { - self.check_module_privacy(handler, src, dst)?; + self.check_module_privacy(handler, src)?; let decl_engine = engines.de(); - let src_ns = self.check_submodule(handler, src)?; - match src_ns.symbols.get(enum_name).cloned() { + let src_mod = self.check_submodule(handler, src)?; + match src_mod.items().symbols.get(enum_name).cloned() { Some(decl) => { if !decl.visibility(decl_engine).is_public() && !is_ancestor(src, dst) { handler.emit_err(CompileError::ImportPrivateSymbol { @@ -504,14 +525,16 @@ impl Module { enum_decl.variants.iter().find(|v| v.name == *variant_name) { // import it this way. - let dst_ns = &mut self[dst]; + let dst_mod = &mut self[dst]; let mut add_synonym = |name| { - if let Some((_, GlobImport::No, _, _)) = dst_ns.use_synonyms.get(name) { + if let Some((_, GlobImport::No, _, _)) = + dst_mod.items().use_synonyms.get(name) + { handler.emit_err(CompileError::ShadowsOtherSymbol { name: name.into(), }); } - dst_ns.use_synonyms.insert( + dst_mod.items_mut().use_synonyms.insert( name.clone(), ( src.to_vec(), @@ -528,7 +551,8 @@ impl Module { match alias { Some(alias) => { add_synonym(&alias); - dst_ns + dst_mod + .items_mut() .use_aliases .insert(alias.as_str().to_string(), variant_name.clone()); } @@ -564,18 +588,18 @@ impl Module { pub(crate) fn variant_star_import( &mut self, handler: &Handler, + engines: &Engines, src: &Path, dst: &Path, - engines: &Engines, enum_name: &Ident, is_src_absolute: bool, ) -> Result<(), ErrorEmitted> { - self.check_module_privacy(handler, src, dst)?; + self.check_module_privacy(handler, src)?; let decl_engine = engines.de(); - let src_ns = self.check_submodule(handler, src)?; - match src_ns.symbols.get(enum_name).cloned() { + let src_mod = self.check_submodule(handler, src)?; + match src_mod.items().symbols.get(enum_name).cloned() { Some(decl) => { if !decl.visibility(decl_engine).is_public() && !is_ancestor(src, dst) { handler.emit_err(CompileError::ImportPrivateSymbol { @@ -601,8 +625,8 @@ impl Module { let variant_name = &variant_decl.name; // import it this way. - let dst_ns = &mut self[dst]; - dst_ns.use_synonyms.insert( + let dst_mod = &mut self[dst]; + dst_mod.items_mut().use_synonyms.insert( variant_name.clone(), ( src.to_vec(), @@ -634,12 +658,8 @@ impl Module { Ok(()) } - fn check_module_privacy( - &self, - handler: &Handler, - src: &Path, - dst: &Path, - ) -> Result<(), ErrorEmitted> { + fn check_module_privacy(&self, handler: &Handler, src: &Path) -> Result<(), ErrorEmitted> { + let dst = &self.mod_path; // you are always allowed to access your ancestor's symbols if !is_ancestor(src, dst) { // we don't check the first prefix because direct children are always accessible @@ -945,6 +965,7 @@ impl Module { type_id }; let item_ref = self + .items() .implemented_traits .get_trait_item_for_type(handler, engines, symbol, type_id, as_trait)?; match item_ref { @@ -964,10 +985,11 @@ impl Module { self_type: Option, ) -> Result { let true_symbol = self[mod_path] + .items() .use_aliases .get(symbol.as_str()) .unwrap_or(symbol); - match module.use_synonyms.get(symbol) { + match module.items().use_synonyms.get(symbol) { Some((_, _, decl @ ty::TyDecl::EnumVariantDecl { .. }, _)) => Ok(decl.clone()), Some((src_path, _, _, _)) if mod_path != src_path => { // If the symbol is imported, before resolving to it, @@ -979,12 +1001,13 @@ impl Module { // - non-glob import, in which case we will already have a name clash reported // as an error, but still have to resolve to the local module symbol // if it exists. - match module.symbols.get(true_symbol) { + match module.items().symbols.get(true_symbol) { Some(decl) => Ok(decl.clone()), None => self.resolve_symbol(handler, engines, src_path, true_symbol, self_type), } } _ => module + .items() .check_symbol(true_symbol) .map_err(|e| handler.emit_err(e)) .cloned(), @@ -992,19 +1015,6 @@ impl Module { } } -impl std::ops::Deref for Module { - type Target = Items; - fn deref(&self) -> &Self::Target { - &self.items - } -} - -impl std::ops::DerefMut for Module { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.items - } -} - impl<'a> std::ops::Index<&'a Path> for Module { type Output = Module; fn index(&self, path: &'a Path) -> &Self::Output { diff --git a/sway-core/src/semantic_analysis/namespace/namespace.rs b/sway-core/src/semantic_analysis/namespace/namespace.rs index d71ff6526b3..7d68e5a27d6 100644 --- a/sway-core/src/semantic_analysis/namespace/namespace.rs +++ b/sway-core/src/semantic_analysis/namespace/namespace.rs @@ -1,5 +1,5 @@ use crate::{ - language::{ty, CallPath, Visibility}, + language::{ty, ty::TyTraitItem, CallPath, Visibility}, Engines, Ident, TypeId, }; @@ -70,9 +70,13 @@ impl Namespace { &self.root } - /// A mutable reference to the root of the project namespace. - pub fn root_mut(&mut self) -> &mut Root { - &mut self.root + pub fn root_module(&self) -> &Module { + &self.root.module + } + + /// The name of the root module + pub fn root_module_name(&self) -> &Option { + &self.root.module.name } /// Access to the current [Module], i.e. the module at the inner `mod_path`. @@ -91,59 +95,12 @@ impl Namespace { &mut self.root.module[&self.mod_path] } - /// Short-hand for calling [Root::resolve_symbol] on `root` with the `mod_path`. - pub(crate) fn resolve_symbol( - &self, - handler: &Handler, - engines: &Engines, - symbol: &Ident, - self_type: Option, - ) -> Result { - self.root - .resolve_symbol(handler, engines, &self.mod_path, symbol, self_type) - } - - /// Short-hand for calling [Root::resolve_call_path] on `root` with the `mod_path`. - pub(crate) fn resolve_call_path( + pub fn check_absolute_path_to_submodule( &self, handler: &Handler, - engines: &Engines, - call_path: &CallPath, - self_type: Option, - ) -> Result { - self.root - .resolve_call_path(handler, engines, &self.mod_path, call_path, self_type) - } - - /// "Enter" the submodule at the given path by returning a new [SubmoduleNamespace]. - /// - /// Here we temporarily change `mod_path` to the given `dep_mod_path` and wrap `self` in a - /// [SubmoduleNamespace] type. When dropped, the [SubmoduleNamespace] resets the `mod_path` - /// back to the original path so that we can continue type-checking the current module after - /// finishing with the dependency. - pub(crate) fn enter_submodule( - &mut self, - mod_name: Ident, - visibility: Visibility, - module_span: Span, - ) -> SubmoduleNamespace { - let init = self.init.clone(); - self.submodules.entry(mod_name.to_string()).or_insert(init); - let submod_path: Vec<_> = self - .mod_path - .iter() - .cloned() - .chain(Some(mod_name.clone())) - .collect(); - let parent_mod_path = std::mem::replace(&mut self.mod_path, submod_path); - self.name = Some(mod_name); - self.span = Some(module_span); - self.visibility = visibility; - self.is_external = false; - SubmoduleNamespace { - namespace: self, - parent_mod_path, - } + path: &[Ident], + ) -> Result<&Module, ErrorEmitted> { + self.root.module.check_submodule(handler, path) } /// Returns true if the current module being checked is a direct or indirect submodule of @@ -164,7 +121,7 @@ impl Namespace { ) -> bool { // `mod_path` does not contain the root name, so we have to separately check // that the root name is equal to the module package name. - let root_name = match &self.root.name { + let root_name = match &self.root.module.name { Some(name) => name, None => panic!("Root module must always have a name."), }; @@ -198,7 +155,7 @@ impl Namespace { /// Returns true if the module given by the `absolute_module_path` is external /// to the current package. External modules are imported in the `Forc.toml` file. pub(crate) fn module_is_external(&self, absolute_module_path: &Path) -> bool { - let root_name = match &self.root.name { + let root_name = match &self.root.module.name { Some(name) => name, None => panic!("Root module must always have a name."), }; @@ -207,17 +164,94 @@ impl Namespace { root_name != &absolute_module_path[0] } -} -impl std::ops::Deref for Namespace { - type Target = Module; - fn deref(&self) -> &Self::Target { - self.module() + pub fn get_root_trait_item_for_type( + &self, + handler: &Handler, + engines: &Engines, + name: &Ident, + type_id: TypeId, + as_trait: Option, + ) -> Result { + self.root + .module + .items() + .implemented_traits + .get_trait_item_for_type(handler, engines, name, type_id, as_trait) } -} -impl std::ops::DerefMut for Namespace { - fn deref_mut(&mut self) -> &mut Self::Target { + pub fn resolve_root_symbol( + &self, + handler: &Handler, + engines: &Engines, + mod_path: &Path, + symbol: &Ident, + self_type: Option, + ) -> Result { + self.root + .module + .resolve_symbol(handler, engines, mod_path, symbol, self_type) + } + + /// Short-hand for calling [Root::resolve_symbol] on `root` with the `mod_path`. + pub(crate) fn resolve_symbol( + &self, + handler: &Handler, + engines: &Engines, + symbol: &Ident, + self_type: Option, + ) -> Result { + self.root + .module + .resolve_symbol(handler, engines, &self.mod_path, symbol, self_type) + } + + /// Short-hand for calling [Root::resolve_call_path] on `root` with the `mod_path`. + pub(crate) fn resolve_call_path( + &self, + handler: &Handler, + engines: &Engines, + call_path: &CallPath, + self_type: Option, + ) -> Result { + self.root + .module + .resolve_call_path(handler, engines, &self.mod_path, call_path, self_type) + } + + /// "Enter" the submodule at the given path by returning a new [SubmoduleNamespace]. + /// + /// Here we temporarily change `mod_path` to the given `dep_mod_path` and wrap `self` in a + /// [SubmoduleNamespace] type. When dropped, the [SubmoduleNamespace] resets the `mod_path` + /// back to the original path so that we can continue type-checking the current module after + /// finishing with the dependency. + pub(crate) fn enter_submodule( + &mut self, + mod_name: Ident, + visibility: Visibility, + module_span: Span, + ) -> SubmoduleNamespace { + let init = self.init.clone(); self.module_mut() + .submodules + .entry(mod_name.to_string()) + .or_insert(init); + let submod_path: Vec<_> = self + .mod_path + .iter() + .cloned() + .chain(Some(mod_name.clone())) + .collect(); + let parent_mod_path = std::mem::replace(&mut self.mod_path, submod_path); + // self.module() now refers to a different module, so refetch + let new_module = self.module_mut(); + new_module.name = Some(mod_name); + new_module.span = Some(module_span); + new_module.visibility = visibility; + new_module.is_external = false; + SubmoduleNamespace { + namespace: self, + parent_mod_path, + } } } diff --git a/sway-core/src/semantic_analysis/namespace/root.rs b/sway-core/src/semantic_analysis/namespace/root.rs index b63915fe3c4..c0840c05744 100644 --- a/sway-core/src/semantic_analysis/namespace/root.rs +++ b/sway-core/src/semantic_analysis/namespace/root.rs @@ -13,19 +13,6 @@ pub struct Root { pub(crate) module: Module, } -impl std::ops::Deref for Root { - type Target = Module; - fn deref(&self) -> &Self::Target { - &self.module - } -} - -impl std::ops::DerefMut for Root { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.module - } -} - impl From for Root { fn from(module: Module) -> Self { Root { module } diff --git a/sway-core/src/semantic_analysis/type_check_context.rs b/sway-core/src/semantic_analysis/type_check_context.rs index d42cf959bc5..f09193b4a52 100644 --- a/sway-core/src/semantic_analysis/type_check_context.rs +++ b/sway-core/src/semantic_analysis/type_check_context.rs @@ -443,7 +443,7 @@ impl<'a> TypeCheckContext<'a> { name: Ident, item: TyDecl, ) -> Result<(), ErrorEmitted> { - self.namespace.insert_symbol( + self.namespace.module_mut().items_mut().insert_symbol( handler, name, item, @@ -480,6 +480,7 @@ impl<'a> TypeCheckContext<'a> { } => { let type_decl_opt = if let Some(root_type_id) = root_type_id { self.namespace + .module() .resolve_call_path_and_root_type_id( handler, self.engines, @@ -559,11 +560,13 @@ impl<'a> TypeCheckContext<'a> { name, trait_type_id, } => { - let item_ref = self - .namespace - .root - .implemented_traits - .get_trait_item_for_type(handler, self.engines, &name, trait_type_id, None)?; + let item_ref = self.namespace.get_root_trait_item_for_type( + handler, + self.engines, + &name, + trait_type_id, + None, + )?; if let TyTraitItem::Type(type_ref) = item_ref { let type_decl = self.engines.de().get_type(type_ref.id()); if let Some(ty) = &type_decl.ty { @@ -674,7 +677,7 @@ impl<'a> TypeCheckContext<'a> { mod_path: &Path, call_path: &CallPath, ) -> Result { - let (decl, mod_path) = self.namespace.root.resolve_call_path_and_mod_path( + let (decl, mod_path) = self.namespace.root.module.resolve_call_path_and_mod_path( handler, self.engines, mod_path, @@ -695,7 +698,9 @@ impl<'a> TypeCheckContext<'a> { // check the visibility of the call path elements // we don't check the first prefix because direct children are always accessible for prefix in iter_prefixes(&call_path.prefixes).skip(1) { - let module = self.namespace.root.check_submodule(handler, prefix)?; + let module = self + .namespace + .check_absolute_path_to_submodule(handler, prefix)?; if module.visibility.is_private() { let prefix_last = prefix[prefix.len() - 1].clone(); handler.emit_err(CompileError::ImportPrivateModule { @@ -773,14 +778,17 @@ impl<'a> TypeCheckContext<'a> { _ => None, }; - self.namespace.root.resolve_call_path_and_root_type_id( - handler, - self.engines, - root_type_id, - as_trait_opt, - &qualified_call_path.call_path, - self.self_type(), - ) + self.namespace + .root + .module + .resolve_call_path_and_root_type_id( + handler, + self.engines, + root_type_id, + as_trait_opt, + &qualified_call_path.call_path, + self.self_type(), + ) } else { self.resolve_call_path_with_visibility_check_and_modpath( handler, @@ -930,11 +938,12 @@ impl<'a> TypeCheckContext<'a> { // grab the local module let local_module = self .namespace - .root() - .check_submodule(handler, &self.namespace.mod_path)?; + .check_absolute_path_to_submodule(handler, &self.namespace.mod_path)?; // grab the local items from the local module - let local_items = local_module.get_items_for_type(self.engines, type_id); + let local_items = local_module + .items() + .get_items_for_type(self.engines, type_id); // resolve the type let type_id = self @@ -953,11 +962,12 @@ impl<'a> TypeCheckContext<'a> { // grab the module where the type itself is declared let type_module = self .namespace - .root() - .check_submodule(handler, item_prefix)?; + .check_absolute_path_to_submodule(handler, item_prefix)?; // grab the items from where the type is declared - let mut type_items = type_module.get_items_for_type(self.engines, type_id); + let mut type_items = type_module + .items() + .get_items_for_type(self.engines, type_id); let mut items = local_items; items.append(&mut type_items); @@ -1246,11 +1256,11 @@ impl<'a> TypeCheckContext<'a> { src: &Path, is_absolute: bool, ) -> Result<(), ErrorEmitted> { - self.namespace.root.star_import( + self.namespace.root.module.star_import( handler, + self.engines, src, &self.namespace.mod_path, - self.engines, is_absolute, ) } @@ -1263,11 +1273,11 @@ impl<'a> TypeCheckContext<'a> { enum_name: &Ident, is_absolute: bool, ) -> Result<(), ErrorEmitted> { - self.namespace.root.variant_star_import( + self.namespace.root.module.variant_star_import( handler, + self.engines, src, &self.namespace.mod_path, - self.engines, enum_name, is_absolute, ) @@ -1281,7 +1291,7 @@ impl<'a> TypeCheckContext<'a> { alias: Option, is_absolute: bool, ) -> Result<(), ErrorEmitted> { - self.namespace.root.self_import( + self.namespace.root.module.self_import( handler, self.engines, src, @@ -1300,7 +1310,7 @@ impl<'a> TypeCheckContext<'a> { alias: Option, is_absolute: bool, ) -> Result<(), ErrorEmitted> { - self.namespace.root.item_import( + self.namespace.root.module.item_import( handler, self.engines, src, @@ -1322,7 +1332,7 @@ impl<'a> TypeCheckContext<'a> { alias: Option, is_absolute: bool, ) -> Result<(), ErrorEmitted> { - self.namespace.root.variant_import( + self.namespace.root.module.variant_import( handler, self.engines, src, @@ -1351,18 +1361,22 @@ impl<'a> TypeCheckContext<'a> { // this inserting and getting in `get_methods_for_type_and_trait_name`. let full_trait_name = trait_name.to_fullpath(self.namespace); - self.namespace.implemented_traits.insert( - handler, - full_trait_name, - trait_type_args, - type_id, - items, - impl_span, - trait_decl_span, - is_impl_self, - is_extending_existing_impl, - self.engines, - ) + self.namespace + .module_mut() + .items_mut() + .implemented_traits + .insert( + handler, + full_trait_name, + trait_type_args, + type_id, + items, + impl_span, + trait_decl_span, + is_impl_self, + is_extending_existing_impl, + self.engines, + ) } pub(crate) fn get_items_for_type_and_trait_name( @@ -1384,6 +1398,8 @@ impl<'a> TypeCheckContext<'a> { let trait_name = trait_name.to_fullpath(self.namespace); self.namespace + .module() + .items() .implemented_traits .get_items_for_type_and_trait_name_and_trait_type_arguments( self.engines, @@ -1568,6 +1584,8 @@ impl<'a> TypeCheckContext<'a> { pub(crate) fn insert_trait_implementation_for_type(&mut self, type_id: TypeId) { self.namespace + .module_mut() + .items_mut() .implemented_traits .insert_for_type(self.engines, type_id); } @@ -1591,6 +1609,8 @@ impl<'a> TypeCheckContext<'a> { let handler = Handler::default(); self.namespace + .module_mut() + .items_mut() .implemented_traits .check_if_trait_constraints_are_satisfied_for_type( &handler, diff --git a/sway-core/src/type_system/ast_elements/binding.rs b/sway-core/src/type_system/ast_elements/binding.rs index 11f7c7e4d3c..58dc908c121 100644 --- a/sway-core/src/type_system/ast_elements/binding.rs +++ b/sway-core/src/type_system/ast_elements/binding.rs @@ -172,8 +172,7 @@ impl TypeBinding> { // find the module that the symbol is in let type_info_prefix = ctx.namespace.find_module_path(&self.inner.prefixes); ctx.namespace - .root() - .check_submodule(handler, &type_info_prefix)?; + .check_absolute_path_to_submodule(handler, &type_info_prefix)?; // create the type info object let type_info = type_info.apply_type_arguments( diff --git a/sway-core/src/type_system/ast_elements/type_parameter.rs b/sway-core/src/type_system/ast_elements/type_parameter.rs index 32594e835de..f29c96cbcdf 100644 --- a/sway-core/src/type_system/ast_elements/type_parameter.rs +++ b/sway-core/src/type_system/ast_elements/type_parameter.rs @@ -164,14 +164,14 @@ impl TypeParameter { let name_b = Ident::new_with_override("Self".into(), self.name_ident.span()); let const_shadowing_mode = ctx.const_shadowing_mode(); let generic_shadowing_mode = ctx.generic_shadowing_mode(); - let _ = ctx.namespace.insert_symbol( + let _ = ctx.namespace.module_mut().items_mut().insert_symbol( handler, name_a, type_parameter_decl.clone(), const_shadowing_mode, generic_shadowing_mode, ); - let _ = ctx.namespace.insert_symbol( + let _ = ctx.namespace.module_mut().items_mut().insert_symbol( handler, name_b, type_parameter_decl, @@ -348,7 +348,13 @@ impl TypeParameter { // When type parameter is from parent then it was already inserted. // Instead of inserting a type with same name we unify them. if type_parameter.is_from_parent { - if let Some(sy) = ctx.namespace.symbols.get(&type_parameter.name_ident) { + if let Some(sy) = ctx + .namespace + .module() + .items() + .symbols + .get(&type_parameter.name_ident) + { match sy { ty::TyDecl::GenericTypeForFunctionScope(ty::GenericTypeForFunctionScope { type_id: sy_type_id, @@ -459,6 +465,8 @@ impl TypeParameter { // Check to see if the trait constraints are satisfied. match ctx .namespace + .module_mut() + .items_mut() .implemented_traits .check_if_trait_constraints_are_satisfied_for_type( handler, diff --git a/sway-core/src/type_system/id.rs b/sway-core/src/type_system/id.rs index c80d19f2e39..57844ecaddc 100644 --- a/sway-core/src/type_system/id.rs +++ b/sway-core/src/type_system/id.rs @@ -577,6 +577,8 @@ impl TypeId { let mut found_error = false; let generic_trait_constraints_trait_names_and_args = ctx .namespace + .module() + .items() .implemented_traits .get_trait_names_and_type_arguments_for_type(engines, *structure_type_id); for structure_trait_constraint in structure_trait_constraints { diff --git a/sway-lsp/src/capabilities/hover/hover_link_contents.rs b/sway-lsp/src/capabilities/hover/hover_link_contents.rs index 67877523ff0..e5c8001ebf1 100644 --- a/sway-lsp/src/capabilities/hover/hover_link_contents.rs +++ b/sway-lsp/src/capabilities/hover/hover_link_contents.rs @@ -91,7 +91,10 @@ impl<'a> HoverLinkContents<'a> { pub fn add_implementations_for_trait(&mut self, trait_decl: &TyTraitDecl) { if let Some(namespace) = self.session.namespace() { let call_path = CallPath::from(trait_decl.name.clone()).to_fullpath(&namespace); - let impl_spans = namespace.get_impl_spans_for_trait_name(&call_path); + let impl_spans = namespace + .module() + .items() + .get_impl_spans_for_trait_name(&call_path); self.add_implementations(&trait_decl.span(), impl_spans); } } @@ -99,7 +102,10 @@ impl<'a> HoverLinkContents<'a> { /// Adds implementations of the given type to the list of implementations using the [TyDecl]. pub fn add_implementations_for_decl(&mut self, ty_decl: &TyDecl) { if let Some(namespace) = self.session.namespace() { - let impl_spans = namespace.get_impl_spans_for_decl(self.engines, ty_decl); + let impl_spans = namespace + .module() + .items() + .get_impl_spans_for_decl(self.engines, ty_decl); self.add_implementations(&ty_decl.span(), impl_spans); } } @@ -107,7 +113,10 @@ impl<'a> HoverLinkContents<'a> { /// Adds implementations of the given type to the list of implementations using the [TypeId]. pub fn add_implementations_for_type(&mut self, decl_span: &Span, type_id: &TypeId) { if let Some(namespace) = self.session.namespace() { - let impl_spans = namespace.get_impl_spans_for_type(self.engines, type_id); + let impl_spans = namespace + .module() + .items() + .get_impl_spans_for_type(self.engines, type_id); self.add_implementations(decl_span, impl_spans); } } diff --git a/sway-lsp/src/core/session.rs b/sway-lsp/src/core/session.rs index 48f7c8103bc..a1fff539a38 100644 --- a/sway-lsp/src/core/session.rs +++ b/sway-lsp/src/core/session.rs @@ -186,7 +186,7 @@ impl Session { if let Some(TypedAstToken::TypedFunctionDeclaration(fn_decl)) = fn_token.typed.clone() { let program = compiled_program.typed.clone()?; return Some(capabilities::completion::to_completion_items( - &program.root.namespace, + program.root.namespace.module().items(), &self.engines.read(), ident_to_complete, &fn_decl, @@ -403,7 +403,11 @@ pub fn traverse( // Create context with write guards to make readers wait until the update to token_map is complete. // This operation is fast because we already have the compile results. - let ctx = ParseContext::new(&session.token_map, engines, &typed_program.root.namespace); + let ctx = ParseContext::new( + &session.token_map, + engines, + typed_program.root.namespace.module(), + ); // The final element in the results is the main program. if i == results_len - 1 { diff --git a/sway-lsp/src/traverse/typed_tree.rs b/sway-lsp/src/traverse/typed_tree.rs index 5f323cd887e..13c17bbbd7b 100644 --- a/sway-lsp/src/traverse/typed_tree.rs +++ b/sway-lsp/src/traverse/typed_tree.rs @@ -129,7 +129,7 @@ impl Parse for ty::TySideEffect { if let Some(decl_ident) = ctx .namespace .submodule(call_path) - .and_then(|module| module.symbols().get(item)) + .and_then(|module| module.items().symbols().get(item)) .and_then(|decl| decl.get_decl_ident()) { // Update the symbol kind to match the declarations symbol kind @@ -465,7 +465,7 @@ impl Parse for ty::TyExpression { if let Some(abi_def_ident) = ctx .namespace .submodule(&abi_name.prefixes) - .and_then(|module| module.symbols().get(&abi_name.suffix)) + .and_then(|module| module.items().symbols().get(&abi_name.suffix)) .and_then(|decl| decl.get_decl_ident()) { token.type_def = Some(TypeDefinition::Ident(abi_def_ident)); @@ -479,7 +479,9 @@ impl Parse for ty::TyExpression { &ctx.ident(&Ident::new(storage_access.storage_keyword_span.clone())), ) { token.typed = Some(TypedAstToken::TypedStorageAccess(storage_access.clone())); - if let Some(storage) = ctx.namespace.get_declared_storage(ctx.engines.de()) { + if let Some(storage) = + ctx.namespace.items().get_declared_storage(ctx.engines.de()) + { token.type_def = Some(TypeDefinition::Ident(storage.storage_keyword.clone())); } @@ -495,6 +497,7 @@ impl Parse for ty::TyExpression { )); if let Some(storage_field) = ctx .namespace + .items() .get_declared_storage(ctx.engines.de()) .and_then(|storage| { storage @@ -1193,7 +1196,12 @@ fn collect_call_path_tree(ctx: &ParseContext, tree: &CallPathTree, type_arg: &Ty if let Some(abi_def_ident) = ctx .namespace .submodule(&abi_call_path.call_path.prefixes) - .and_then(|module| module.symbols().get(&abi_call_path.call_path.suffix)) + .and_then(|module| { + module + .items() + .symbols() + .get(&abi_call_path.call_path.suffix) + }) .and_then(|decl| decl.get_decl_ident()) { token.type_def = Some(TypeDefinition::Ident(abi_def_ident)); @@ -1371,7 +1379,7 @@ fn collect_trait_constraint( if let Some(trait_def_ident) = ctx .namespace .submodule(&trait_name.prefixes) - .and_then(|module| module.symbols().get(&trait_name.suffix)) + .and_then(|module| module.items().symbols().get(&trait_name.suffix)) .and_then(|decl| decl.get_decl_ident()) { token.type_def = Some(TypeDefinition::Ident(trait_def_ident)); diff --git a/test/src/ir_generation/mod.rs b/test/src/ir_generation/mod.rs index 4553bc1dba4..815ef8a7aa2 100644 --- a/test/src/ir_generation/mod.rs +++ b/test/src/ir_generation/mod.rs @@ -538,13 +538,19 @@ fn compile_core(build_target: BuildTarget, engines: &Engines) -> namespace::Modu Some(typed_program) => { // Create a module for core and copy the compiled modules into it. Unfortunately we // can't get mutable access to move them out so they're cloned. - let core_module = typed_program.root.namespace.submodules().into_iter().fold( - namespace::Module::default(), - |mut core_mod, (name, sub_mod)| { - core_mod.insert_submodule(name.clone(), sub_mod.clone()); - core_mod - }, - ); + let core_module = typed_program + .root + .namespace + .module() + .submodules() + .into_iter() + .fold( + namespace::Module::default(), + |mut core_mod, (name, sub_mod)| { + core_mod.insert_submodule(name.clone(), sub_mod.clone()); + core_mod + }, + ); // Create a module for std and insert the core module. let mut std_module = namespace::Module::default();