Skip to content

Commit 51e8c9d

Browse files
authored
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.
1 parent 52767cc commit 51e8c9d

File tree

29 files changed

+353
-255
lines changed

29 files changed

+353
-255
lines changed

forc-pkg/src/pkg.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ pub struct CompiledPackage {
179179
pub program_abi: ProgramABI,
180180
pub storage_slots: Vec<StorageSlot>,
181181
pub bytecode: BuiltPackageBytecode,
182-
pub namespace: namespace::Root,
182+
pub root_module: namespace::Module,
183183
pub warnings: Vec<CompileWarning>,
184184
pub metrics: PerformanceData,
185185
}
@@ -1656,18 +1656,18 @@ pub fn dependency_namespace(
16561656

16571657
let _ = namespace.star_import_with_reexports(
16581658
&Handler::default(),
1659+
engines,
16591660
&[CORE, PRELUDE].map(|s| Ident::new_no_span(s.into())),
16601661
&[],
1661-
engines,
16621662
true,
16631663
);
16641664

16651665
if has_std_dep(graph, node) {
16661666
let _ = namespace.star_import_with_reexports(
16671667
&Handler::default(),
1668+
engines,
16681669
&[STD, PRELUDE].map(|s| Ident::new_no_span(s.into())),
16691670
&[],
1670-
engines,
16711671
true,
16721672
);
16731673
}
@@ -1807,7 +1807,7 @@ pub fn compile(
18071807
let storage_slots = typed_program.storage_slots.clone();
18081808
let tree_type = typed_program.kind.tree_type();
18091809

1810-
let namespace = typed_program.root.namespace.clone().into();
1810+
let namespace = typed_program.root.namespace.clone();
18111811

18121812
if handler.has_errors() {
18131813
return fail(handler);
@@ -1932,7 +1932,7 @@ pub fn compile(
19321932
storage_slots,
19331933
tree_type,
19341934
bytecode,
1935-
namespace,
1935+
root_module: namespace.root_module().clone(),
19361936
warnings,
19371937
metrics,
19381938
};
@@ -2430,9 +2430,9 @@ pub fn build(
24302430
}
24312431

24322432
if let TreeType::Library = compiled.tree_type {
2433-
let mut namespace = namespace::Module::from(compiled.namespace);
2434-
namespace.name = Some(Ident::new_no_span(pkg.name.clone()));
2435-
lib_namespace_map.insert(node, namespace);
2433+
let mut root_module = compiled.root_module;
2434+
root_module.name = Some(Ident::new_no_span(pkg.name.clone()));
2435+
lib_namespace_map.insert(node, root_module);
24362436
}
24372437
source_map.insert_dependency(descriptor.manifest_file.dir());
24382438

@@ -2679,9 +2679,9 @@ pub fn check(
26792679
match programs.typed.as_ref() {
26802680
Ok(typed_program) => {
26812681
if let TreeType::Library = typed_program.kind.tree_type() {
2682-
let mut namespace = typed_program.root.namespace.clone();
2683-
namespace.name = Some(Ident::new_no_span(pkg.name.clone()));
2684-
namespace.span = Some(
2682+
let mut module = typed_program.root.namespace.module().clone();
2683+
module.name = Some(Ident::new_no_span(pkg.name.clone()));
2684+
module.span = Some(
26852685
Span::new(
26862686
manifest.entry_string()?,
26872687
0,
@@ -2690,7 +2690,7 @@ pub fn check(
26902690
)
26912691
.unwrap(),
26922692
);
2693-
lib_namespace_map.insert(node, namespace.module().clone());
2693+
lib_namespace_map.insert(node, module);
26942694
}
26952695

26962696
source_map.insert_dependency(manifest.dir());

sway-core/src/abi_generation/fuel_abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ fn call_path_display(ctx: &mut AbiContext, call_path: &CallPath) -> String {
885885
for (index, prefix) in call_path.prefixes.iter().enumerate() {
886886
let mut skip_prefix = false;
887887
if index == 0 {
888-
if let Some(root_name) = ctx.program.root.namespace.name.clone() {
888+
if let Some(root_name) = &ctx.program.root.namespace.module().name {
889889
if prefix.as_str() == root_name.as_str() {
890890
skip_prefix = true;
891891
}

sway-core/src/ir_generation.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pub fn compile_program<'eng>(
6767
engines,
6868
&mut ctx,
6969
main_function,
70-
&root.namespace,
70+
root.namespace.module(),
7171
declarations,
7272
&logged_types,
7373
&messages_types,
@@ -77,7 +77,7 @@ pub fn compile_program<'eng>(
7777
engines,
7878
&mut ctx,
7979
main_function,
80-
&root.namespace,
80+
root.namespace.module(),
8181
declarations,
8282
&logged_types,
8383
&messages_types,
@@ -86,7 +86,7 @@ pub fn compile_program<'eng>(
8686
ty::TyProgramKind::Contract { abi_entries } => compile::compile_contract(
8787
&mut ctx,
8888
abi_entries,
89-
&root.namespace,
89+
root.namespace.module(),
9090
declarations,
9191
&logged_types,
9292
&messages_types,
@@ -96,7 +96,7 @@ pub fn compile_program<'eng>(
9696
ty::TyProgramKind::Library { .. } => compile::compile_library(
9797
engines,
9898
&mut ctx,
99-
&root.namespace,
99+
root.namespace.module(),
100100
declarations,
101101
&logged_types,
102102
&messages_types,

sway-core/src/ir_generation/compile.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,9 @@ pub(crate) fn compile_constants(
205205
module: Module,
206206
module_ns: &namespace::Module,
207207
) -> Result<(), CompileError> {
208-
for decl_name in module_ns.get_all_declared_symbols() {
208+
for decl_name in module_ns.items().get_all_declared_symbols() {
209209
if let Some(ty::TyDecl::ConstantDecl(ty::ConstantDecl { decl_id, .. })) =
210-
module_ns.symbols.get(decl_name)
210+
module_ns.items().symbols.get(decl_name)
211211
{
212212
let const_decl = engines.de().get_constant(decl_id);
213213
let call_path = const_decl.call_path.clone();

sway-core/src/ir_generation/const_eval.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ pub(crate) fn compile_const_decl(
124124
(_, Some(config_val), _) => Ok(Some(config_val)),
125125
(None, None, Some(module_ns)) => {
126126
// See if we it's a global const and whether we can compile it *now*.
127-
let decl = module_ns.check_symbol(&call_path.suffix);
127+
let decl = module_ns.items().check_symbol(&call_path.suffix);
128128
let const_decl = match const_decl {
129129
Some(decl) => Some(decl),
130130
None => None,

sway-core/src/language/call_path.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,10 @@ impl CallPath {
313313
let mut is_external = false;
314314
let mut is_absolute = false;
315315

316-
if let Some(use_synonym) = namespace.use_synonyms.get(&self.suffix) {
316+
if let Some(use_synonym) = namespace.module().items().use_synonyms.get(&self.suffix) {
317317
synonym_prefixes = use_synonym.0.clone();
318318
is_absolute = use_synonym.3;
319-
let submodule = namespace.submodule(&[use_synonym.0[0].clone()]);
319+
let submodule = namespace.module().submodule(&[use_synonym.0[0].clone()]);
320320
if let Some(submodule) = submodule {
321321
is_external = submodule.is_external;
322322
}
@@ -325,7 +325,7 @@ impl CallPath {
325325
let mut prefixes: Vec<Ident> = vec![];
326326

327327
if !is_external {
328-
if let Some(pkg_name) = &namespace.root().module.name {
328+
if let Some(pkg_name) = &namespace.root_module().name {
329329
prefixes.push(pkg_name.clone());
330330
}
331331

@@ -343,7 +343,7 @@ impl CallPath {
343343
suffix: self.suffix.clone(),
344344
is_absolute: true,
345345
}
346-
} else if let Some(m) = namespace.submodule(&[self.prefixes[0].clone()]) {
346+
} else if let Some(m) = namespace.module().submodule(&[self.prefixes[0].clone()]) {
347347
// If some prefixes are already present, attempt to complete the path by adding the
348348
// package name and the path to the current submodule.
349349
//
@@ -357,7 +357,7 @@ impl CallPath {
357357
}
358358
} else {
359359
let mut prefixes: Vec<Ident> = vec![];
360-
if let Some(pkg_name) = &namespace.root().module.name {
360+
if let Some(pkg_name) = &namespace.root_module().name {
361361
prefixes.push(pkg_name.clone());
362362
}
363363
for mod_path in namespace.mod_path() {
@@ -391,7 +391,7 @@ impl CallPath {
391391
let converted = self.to_fullpath(namespace);
392392

393393
if let Some(first) = converted.prefixes.first() {
394-
if namespace.root().name == Some(first.clone()) {
394+
if namespace.root_module().name == Some(first.clone()) {
395395
return converted.lshift();
396396
}
397397
}

sway-core/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ pub fn parsed_to_ast(
587587
&mut ctx,
588588
&mut md_mgr,
589589
module,
590-
&typed_program.root.namespace,
590+
typed_program.root.namespace.module(),
591591
) {
592592
handler.emit_err(e);
593593
}

sway-core/src/semantic_analysis/ast_node/code_block.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ impl ty::TyCodeBlock {
8484

8585
let never_decl_opt = ctx
8686
.namespace
87-
.root()
88-
.resolve_symbol(
87+
.resolve_root_symbol(
8988
&Handler::default(),
9089
engines,
9190
&never_mod_path,

sway-core/src/semantic_analysis/ast_node/declaration/abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ impl ty::TyAbiDecl {
299299
all_items.push(TyImplItem::Constant(decl_ref.clone()));
300300
let const_shadowing_mode = ctx.const_shadowing_mode();
301301
let generic_shadowing_mode = ctx.generic_shadowing_mode();
302-
let _ = ctx.namespace.insert_symbol(
302+
let _ = ctx.namespace.module_mut().items_mut().insert_symbol(
303303
handler,
304304
const_name.clone(),
305305
ty::TyDecl::ConstantDecl(ty::ConstantDecl {

sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ impl<'a, 'b> AutoImplAbiEncodeContext<'a, 'b> {
502502
// skip module "core"
503503
// Because of ordering, we cannot guarantee auto impl
504504
// for structs inside "core"
505-
if matches!(self.ctx.namespace.root().name.as_ref(), Some(x) if x.as_str() == "core") {
505+
if matches!(self.ctx.namespace.root_module_name(), Some(x) if x.as_str() == "core") {
506506
return false;
507507
}
508508

@@ -531,6 +531,8 @@ impl<'a, 'b> AutoImplAbiEncodeContext<'a, 'b> {
531531
let handler = Handler::default();
532532
self.ctx
533533
.namespace
534+
.module_mut()
535+
.items_mut()
534536
.implemented_traits
535537
.check_if_trait_constraints_are_satisfied_for_type(
536538
&handler,

sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs

+2
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,8 @@ impl TyDecl {
362362

363363
// declarations are not allowed
364364
ctx.namespace
365+
.module_mut()
366+
.items_mut()
365367
.set_storage_declaration(handler, decl_ref.clone())?;
366368
decl_ref.into()
367369
}

sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ impl ty::TyFunctionParameter {
105105
pub fn insert_into_namespace(&self, handler: &Handler, ctx: TypeCheckContext) {
106106
let const_shadowing_mode = ctx.const_shadowing_mode();
107107
let generic_shadowing_mode = ctx.generic_shadowing_mode();
108-
let _ = ctx.namespace.insert_symbol(
108+
let _ = ctx.namespace.module_mut().items_mut().insert_symbol(
109109
handler,
110110
self.name.clone(),
111111
ty::TyDecl::VariableDecl(Box::new(ty::TyVariableDecl {

sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs

+2
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,8 @@ fn type_check_trait_implementation(
620620
// Check to see if the type that we are implementing for implements the
621621
// supertraits of this trait.
622622
ctx.namespace
623+
.module_mut()
624+
.items_mut()
623625
.implemented_traits
624626
.check_if_trait_constraints_are_satisfied_for_type(
625627
handler,

sway-core/src/semantic_analysis/ast_node/declaration/trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ impl TyTraitDecl {
444444
all_items.push(TyImplItem::Constant(decl_ref.clone()));
445445
let const_shadowing_mode = ctx.const_shadowing_mode();
446446
let generic_shadowing_mode = ctx.generic_shadowing_mode();
447-
let _ = ctx.namespace.insert_symbol(
447+
let _ = ctx.namespace.module_mut().items_mut().insert_symbol(
448448
handler,
449449
const_name.clone(),
450450
ty::TyDecl::ConstantDecl(ty::ConstantDecl {

sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs

+15-11
Original file line numberDiff line numberDiff line change
@@ -1023,16 +1023,18 @@ impl ty::TyExpression {
10231023
let decl_engine = ctx.engines.de();
10241024
let engines = ctx.engines();
10251025

1026-
if !ctx.namespace.has_storage_declared() {
1026+
if !ctx.namespace.module().items().has_storage_declared() {
10271027
return Err(handler.emit_err(CompileError::NoDeclaredStorage { span: span.clone() }));
10281028
}
10291029

10301030
let storage_fields = ctx
10311031
.namespace
1032+
.module()
1033+
.items()
10321034
.get_storage_field_descriptors(handler, decl_engine)?;
10331035

10341036
// Do all namespace checking here!
1035-
let (storage_access, mut access_type) = ctx.namespace.apply_storage_load(
1037+
let (storage_access, mut access_type) = ctx.namespace.module().items().apply_storage_load(
10361038
handler,
10371039
ctx.engines,
10381040
ctx.namespace,
@@ -1050,7 +1052,7 @@ impl ty::TyExpression {
10501052
let storage_key_ident = Ident::new_with_override("StorageKey".into(), span.clone());
10511053

10521054
// Search for the struct declaration with the call path above.
1053-
let storage_key_decl_opt = ctx.namespace.root().resolve_symbol(
1055+
let storage_key_decl_opt = ctx.namespace.resolve_root_symbol(
10541056
handler,
10551057
engines,
10561058
&storage_key_mod_path,
@@ -1254,7 +1256,7 @@ impl ty::TyExpression {
12541256
path.push(before.inner.clone());
12551257
let not_module = {
12561258
let h = Handler::default();
1257-
ctx.namespace.check_submodule(&h, &path).is_err()
1259+
ctx.namespace.module().check_submodule(&h, &path).is_err()
12581260
};
12591261

12601262
// Not a module? Not a `Enum::Variant` either?
@@ -1373,6 +1375,7 @@ impl ty::TyExpression {
13731375
is_module = {
13741376
let call_path_binding = unknown_call_path_binding.clone();
13751377
ctx.namespace
1378+
.module()
13761379
.check_submodule(
13771380
&module_probe_handler,
13781381
&[
@@ -2014,13 +2017,14 @@ impl ty::TyExpression {
20142017
}
20152018
};
20162019
let names_vec = names_vec.into_iter().rev().collect::<Vec<_>>();
2017-
let (ty_of_field, _ty_of_parent) = ctx.namespace.find_subfield_type(
2018-
handler,
2019-
ctx.engines(),
2020-
ctx.namespace,
2021-
&base_name,
2022-
&names_vec,
2023-
)?;
2020+
let (ty_of_field, _ty_of_parent) =
2021+
ctx.namespace.module().items().find_subfield_type(
2022+
handler,
2023+
ctx.engines(),
2024+
ctx.namespace,
2025+
&base_name,
2026+
&names_vec,
2027+
)?;
20242028
// type check the reassignment
20252029
let ctx = ctx.with_type_annotation(ty_of_field).with_help_text("");
20262030
let rhs_span = rhs.span();

sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,7 @@ pub(crate) fn resolve_method_name(
439439
.namespace
440440
.find_module_path(&call_path_binding.inner.prefixes);
441441
ctx.namespace
442-
.root()
443-
.check_submodule(handler, &type_info_prefix)?;
442+
.check_absolute_path_to_submodule(handler, &type_info_prefix)?;
444443

445444
// find the method
446445
let decl_ref = ctx.find_method_for_type(
@@ -464,7 +463,7 @@ pub(crate) fn resolve_method_name(
464463
let mut module_path = call_path.prefixes.clone();
465464
if let (Some(root_mod), Some(root_name)) = (
466465
module_path.first().cloned(),
467-
ctx.namespace.root().name.clone(),
466+
ctx.namespace.root_module_name().clone(),
468467
) {
469468
if root_mod.as_str() == root_name.as_str() {
470469
module_path.remove(0);

sway-core/src/semantic_analysis/ast_node/expression/typed_expression/struct_instantiation.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ pub(crate) fn struct_instantiation(
8080
// find the module that the struct decl is in
8181
let type_info_prefix = ctx.namespace.find_module_path(&prefixes);
8282
ctx.namespace
83-
.root()
84-
.check_submodule(handler, &type_info_prefix)?;
83+
.check_absolute_path_to_submodule(handler, &type_info_prefix)?;
8584

8685
// resolve the type of the struct decl
8786
let type_id = ctx
@@ -255,6 +254,8 @@ pub(crate) fn struct_instantiation(
255254
// but that would be a way too much of suggestions, and moreover, it is also not a design pattern/guideline
256255
// that we wish to encourage.
257256
namespace
257+
.module()
258+
.items()
258259
.get_items_for_type(engines, struct_type_id)
259260
.iter()
260261
.filter_map(|item| match item {

sway-core/src/semantic_analysis/ast_node/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ impl ty::TyAstNode {
3434
content: match node.content.clone() {
3535
AstNodeContent::UseStatement(a) => {
3636
let mut is_external = false;
37-
if let Some(submodule) = ctx.namespace.submodule(&[a.call_path[0].clone()]) {
37+
if let Some(submodule) =
38+
ctx.namespace.module().submodule(&[a.call_path[0].clone()])
39+
{
3840
is_external = submodule.is_external;
3941
}
4042
let path = if is_external || a.is_absolute {

0 commit comments

Comments
 (0)