From ccb129f6100bf6f4de56ae0de7a210117c7893fd Mon Sep 17 00:00:00 2001 From: Vaivaswatha N Date: Tue, 13 Feb 2024 16:35:34 +0530 Subject: [PATCH 1/4] Support for register push and pop instructions (#5177) Closes #4883 --- .../allocated_abstract_instruction_set.rs | 100 ++++++++---------- sway-core/src/asm_lang/allocated_ops.rs | 17 ++- .../configurable_consts/json_abi_oracle.json | 20 ++-- .../call_basic_storage/src/main.sw | 2 +- .../call_increment_contract/src/main.sw | 2 +- .../call_storage_enum/src/main.sw | 2 +- .../storage_access_caller/src/main.sw | 2 +- 7 files changed, 76 insertions(+), 69 deletions(-) diff --git a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs index d9403d45222..557879c549b 100644 --- a/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs +++ b/sway-core/src/asm_generation/fuel/allocated_abstract_instruction_set.rs @@ -82,6 +82,28 @@ impl AllocatedAbstractInstructionSet { ) .0; + fn generate_mask(regs: &[&AllocatedRegister]) -> (VirtualImmediate24, VirtualImmediate24) { + let mask = regs.iter().fold((0, 0), |mut accum, reg| { + let reg_id = reg.to_reg_id().to_u8(); + assert!((16..64).contains(®_id)); + let reg_id = reg_id - 16; + let (mask_ref, bit) = if reg_id < 24 { + (&mut accum.0, reg_id) + } else { + (&mut accum.1, reg_id - 24) + }; + // Set bit (from the least significant side) of mask_ref. + *mask_ref |= 1 << bit; + accum + }); + ( + VirtualImmediate24::new(mask.0, Span::dummy()) + .expect("mask should have fit in 24b"), + VirtualImmediate24::new(mask.1, Span::dummy()) + .expect("mask should have fit in 24b"), + ) + } + // Now replace the PUSHA/POPA instructions with STOREs and LOADs. self.ops = self.ops.drain(..).fold(Vec::new(), |mut new_ops, op| { match &op.opcode { @@ -94,35 +116,21 @@ impl AllocatedAbstractInstructionSet { .chain([&AllocatedRegister::Constant(ConstantRegister::LocalsBase)]) .collect::>(); - let stack_use_bytes = regs.len() as u64 * 8; - new_ops.push(AllocatedAbstractOp { - opcode: Either::Left(AllocatedOpcode::MOVE( - AllocatedRegister::Constant(ConstantRegister::Scratch), - AllocatedRegister::Constant(ConstantRegister::StackPointer), - )), - comment: "save base stack value".into(), - owning_span: None, - }); - new_ops.push(AllocatedAbstractOp { - opcode: Either::Left(AllocatedOpcode::CFEI( - VirtualImmediate24::new(stack_use_bytes, Span::dummy()).unwrap(), - )), - comment: "reserve space for saved registers".into(), - owning_span: None, - }); - - regs.into_iter().enumerate().for_each(|(idx, reg)| { - let store_op = AllocatedOpcode::SW( - AllocatedRegister::Constant(ConstantRegister::Scratch), - reg.clone(), - VirtualImmediate12::new(idx as u64, Span::dummy()).unwrap(), - ); + let (mask_l, mask_h) = generate_mask(®s); + if mask_l.value != 0 { new_ops.push(AllocatedAbstractOp { - opcode: Either::Left(store_op), - comment: format!("save {reg}"), + opcode: Either::Left(AllocatedOpcode::PSHL(mask_l)), + comment: "Save registers 16..40".into(), owning_span: None, }); - }) + } + if mask_h.value != 0 { + new_ops.push(AllocatedAbstractOp { + opcode: Either::Left(AllocatedOpcode::PSHH(mask_h)), + comment: "Save registers 40..64".into(), + owning_span: None, + }); + } } Either::Right(ControlFlowOp::PopAll(label)) => { @@ -134,37 +142,21 @@ impl AllocatedAbstractInstructionSet { .chain([&AllocatedRegister::Constant(ConstantRegister::LocalsBase)]) .collect::>(); - let stack_use_bytes = regs.len() as u64 * 8; - new_ops.push(AllocatedAbstractOp { - opcode: Either::Left(AllocatedOpcode::SUBI( - AllocatedRegister::Constant(ConstantRegister::Scratch), - AllocatedRegister::Constant(ConstantRegister::StackPointer), - VirtualImmediate12::new(stack_use_bytes, Span::dummy()).unwrap(), - )), - comment: "save base stack value".into(), - owning_span: None, - }); - - regs.into_iter().enumerate().for_each(|(idx, reg)| { - let load_op = AllocatedOpcode::LW( - reg.clone(), - AllocatedRegister::Constant(ConstantRegister::Scratch), - VirtualImmediate12::new(idx as u64, Span::dummy()).unwrap(), - ); + let (mask_l, mask_h) = generate_mask(®s); + if mask_h.value != 0 { + new_ops.push(AllocatedAbstractOp { + opcode: Either::Left(AllocatedOpcode::POPH(mask_h)), + comment: "Restore registers 40..64".into(), + owning_span: None, + }); + } + if mask_l.value != 0 { new_ops.push(AllocatedAbstractOp { - opcode: Either::Left(load_op), - comment: format!("restore {reg}"), + opcode: Either::Left(AllocatedOpcode::POPL(mask_l)), + comment: "Restore registers 16..40".into(), owning_span: None, }); - }); - - new_ops.push(AllocatedAbstractOp { - opcode: Either::Left(AllocatedOpcode::CFSI( - VirtualImmediate24::new(stack_use_bytes, Span::dummy()).unwrap(), - )), - comment: "recover space from saved registers".into(), - owning_span: None, - }); + } } _otherwise => new_ops.push(op), diff --git a/sway-core/src/asm_lang/allocated_ops.rs b/sway-core/src/asm_lang/allocated_ops.rs index 39f7c0f988b..77b4591d398 100644 --- a/sway-core/src/asm_lang/allocated_ops.rs +++ b/sway-core/src/asm_lang/allocated_ops.rs @@ -43,7 +43,7 @@ impl fmt::Display for AllocatedRegister { } impl AllocatedRegister { - fn to_reg_id(&self) -> fuel_asm::RegId { + pub(crate) fn to_reg_id(&self) -> fuel_asm::RegId { match self { AllocatedRegister::Allocated(a) => fuel_asm::RegId::new(a + 16), AllocatedRegister::Constant(constant) => constant.to_reg_id(), @@ -152,6 +152,10 @@ pub(crate) enum AllocatedOpcode { AllocatedRegister, AllocatedRegister, ), + PSHH(VirtualImmediate24), + PSHL(VirtualImmediate24), + POPH(VirtualImmediate24), + POPL(VirtualImmediate24), SB(AllocatedRegister, AllocatedRegister, VirtualImmediate12), SW(AllocatedRegister, AllocatedRegister, VirtualImmediate12), @@ -309,6 +313,9 @@ impl AllocatedOpcode { MCP(_r1, _r2, _r3) => vec![], MCPI(_r1, _r2, _imm) => vec![], MEQ(r1, _r2, _r3, _r4) => vec![r1], + PSHH(_mask) | PSHL(_mask) | POPH(_mask) | POPL(_mask) => { + panic!("Cannot determine defined registers for register PUSH/POP instructions") + } SB(_r1, _r2, _i) => vec![], SW(_r1, _r2, _i) => vec![], @@ -431,6 +438,10 @@ impl fmt::Display for AllocatedOpcode { MCP(a, b, c) => write!(fmtr, "mcp {a} {b} {c}"), MCPI(a, b, c) => write!(fmtr, "mcpi {a} {b} {c}"), MEQ(a, b, c, d) => write!(fmtr, "meq {a} {b} {c} {d}"), + PSHH(mask) => write!(fmtr, "pshh {mask}"), + PSHL(mask) => write!(fmtr, "pshl {mask}"), + POPH(mask) => write!(fmtr, "poph {mask}"), + POPL(mask) => write!(fmtr, "popl {mask}"), SB(a, b, c) => write!(fmtr, "sb {a} {b} {c}"), SW(a, b, c) => write!(fmtr, "sw {a} {b} {c}"), @@ -596,6 +607,10 @@ impl AllocatedOp { MEQ(a, b, c, d) => { op::MEQ::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.to_reg_id()).into() } + PSHH(mask) => op::PSHH::new(mask.value.into()).into(), + PSHL(mask) => op::PSHL::new(mask.value.into()).into(), + POPH(mask) => op::POPH::new(mask.value.into()).into(), + POPL(mask) => op::POPL::new(mask.value.into()).into(), SB(a, b, c) => op::SB::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(), SW(a, b, c) => op::SW::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(), diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_consts/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_consts/json_abi_oracle.json index 591c41b5643..436f20d5d43 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_consts/json_abi_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_consts/json_abi_oracle.json @@ -7,7 +7,7 @@ "typeArguments": null }, "name": "C0", - "offset": 4604 + "offset": 4284 }, { "configurableType": { @@ -16,7 +16,7 @@ "typeArguments": null }, "name": "C1", - "offset": 4620 + "offset": 4300 }, { "configurableType": { @@ -25,7 +25,7 @@ "typeArguments": null }, "name": "C2", - "offset": 4636 + "offset": 4316 }, { "configurableType": { @@ -34,7 +34,7 @@ "typeArguments": [] }, "name": "C3", - "offset": 4668 + "offset": 4348 }, { "configurableType": { @@ -43,7 +43,7 @@ "typeArguments": [] }, "name": "C4", - "offset": 4684 + "offset": 4364 }, { "configurableType": { @@ -52,7 +52,7 @@ "typeArguments": [] }, "name": "C5", - "offset": 4700 + "offset": 4380 }, { "configurableType": { @@ -61,7 +61,7 @@ "typeArguments": null }, "name": "C6", - "offset": 4716 + "offset": 4396 }, { "configurableType": { @@ -70,7 +70,7 @@ "typeArguments": null }, "name": "C7", - "offset": 4732 + "offset": 4412 }, { "configurableType": { @@ -79,7 +79,7 @@ "typeArguments": null }, "name": "C7_2", - "offset": 4796 + "offset": 4476 }, { "configurableType": { @@ -88,7 +88,7 @@ "typeArguments": null }, "name": "C9", - "offset": 4780 + "offset": 4460 } ], "functions": [ diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw index 9cd643edcd6..50c1c83aceb 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw @@ -2,7 +2,7 @@ script; use basic_storage_abi::{BasicStorage, Quad}; fn main() -> u64 { - let addr = abi(BasicStorage, 0x1cb4847c0c736d7bc3a904728b3695b6a8e83be195ec6652cf9047bbe94f3b64); + let addr = abi(BasicStorage, 0x7ee9d721777c523e408a966d97605116e1f2bbad1c16403446c6d734d46258a6); let key = 0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; let value = 4242; diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw index 8bee79e6315..fdbc8d6ebfd 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw @@ -3,7 +3,7 @@ script; use increment_abi::Incrementor; fn main() -> bool { - let the_abi = abi(Incrementor, 0xf5de8211162a13e64a6d868735b62aad9d01836fe0de22d69db1128a69e86bfc); + let the_abi = abi(Incrementor, 0xa1aa9555466ef3c61914e5426973e2257cb4dcd8311ffbbe0e8850a9742f312d); let _ = the_abi.increment(5); let _ = the_abi.increment(5); let result = the_abi.get(); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw index 1ace8eeeea4..8f52d1f6a2e 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw @@ -3,7 +3,7 @@ script; use storage_enum_abi::*; fn main() -> u64 { - let contract_id = 0x2c6686f3a059e41298f5680c92a8effdc628cf86ac293b84ea9fc10fa1fd7906; + let contract_id = 0x097ea9a771b69bf349375a0d6db542e9c730194de4bcd27e4e6665ffb107dfaf; let caller = abi(StorageEnum, contract_id); let res = caller.read_write_enums(); diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw index 8ebe9510eea..e4170911cf1 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw @@ -4,7 +4,7 @@ use storage_access_abi::*; use std::hash::*; fn main() -> bool { - let contract_id = 0x9f807040099c184c7784fd61e1c9d200244d3e2130a486a32c6a20a90cf3616f; + let contract_id = 0xcd976bf8d7f3a9b54416c215ee0c732cbae4f9221e281fbc6c6aa8f428f03eb1; let caller = abi(StorageAccess, contract_id); caller.set_boolean(true); From cdb82e2d9f37d214510172464cb6f9468b24be2d Mon Sep 17 00:00:00 2001 From: Sudhakar Verma <10460978+sudhackar@users.noreply.github.com> Date: Wed, 14 Feb 2024 04:27:34 +0530 Subject: [PATCH 2/4] swayfmt: fix indentation after where in fn (#5468) (#5578) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description This is a small fix to match the indentation for opening brace after a where clause is seen. This should fix #5468 cc: @Braqzen The change is near trivial. ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [ ] 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. - [ ] 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: Kaya Gökalp Co-authored-by: Sophie Dankel <47993817+sdankel@users.noreply.github.com> --- sway-lib-std/src/storage/storage_map.sw | 8 +++--- swayfmt/src/items/item_fn/mod.rs | 3 ++- swayfmt/tests/mod.rs | 34 +++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/sway-lib-std/src/storage/storage_map.sw b/sway-lib-std/src/storage/storage_map.sw index 4b41e3647d9..0ef9ce402a3 100644 --- a/sway-lib-std/src/storage/storage_map.sw +++ b/sway-lib-std/src/storage/storage_map.sw @@ -53,7 +53,7 @@ where pub fn insert(self, key: K, value: V) where K: Hash, -{ + { let key = sha256((key, self.field_id)); write::(key, 0, value); } @@ -87,7 +87,7 @@ where pub fn get(self, key: K) -> StorageKey where K: Hash, -{ + { StorageKey::::new( sha256((key, self.field_id)), 0, @@ -129,7 +129,7 @@ where pub fn remove(self, key: K) -> bool where K: Hash, -{ + { let key = sha256((key, self.slot)); clear::(key, 0) } @@ -180,7 +180,7 @@ where pub fn try_insert(self, key: K, value: V) -> Result> where K: Hash, -{ + { let key = sha256((key, self.field_id)); let val = read::(key, 0); diff --git a/swayfmt/src/items/item_fn/mod.rs b/swayfmt/src/items/item_fn/mod.rs index ae2274d7749..35d14ae80f9 100644 --- a/swayfmt/src/items/item_fn/mod.rs +++ b/swayfmt/src/items/item_fn/mod.rs @@ -83,7 +83,8 @@ impl CurlyBrace for ItemFn { let open_brace = Delimiter::Brace.as_open_char(); match formatter.shape.code_line.has_where_clause { true => { - write!(line, "{open_brace}")?; + let indent_str = formatter.indent_to_str()?; + write!(line, "{indent_str}{open_brace}")?; formatter.shape.code_line.update_where_clause(false); } false => { diff --git a/swayfmt/tests/mod.rs b/swayfmt/tests/mod.rs index 552ffa83a7e..b71f2f148c4 100644 --- a/swayfmt/tests/mod.rs +++ b/swayfmt/tests/mod.rs @@ -2903,3 +2903,37 @@ pub fn from_be_bytes(bytes: [u8; 32]) -> Self { "#, ); } + +#[test] +fn impl_func_where() { + check( + r#"library; + + impl Foo> + where + K: Hash, + { + pub fn baz(self, _: K, _: V) + where + K: Hash, + { + debug(); + } + } + "#, + r#"library; + +impl Foo> +where + K: Hash, +{ + pub fn baz(self, _: K, _: V) + where + K: Hash, + { + debug(); + } +} +"#, + ); +} From 304317cc4ad4bc9e5600c9c7b001f918abe2fcee Mon Sep 17 00:00:00 2001 From: Sophie Dankel <47993817+sdankel@users.noreply.github.com> Date: Tue, 13 Feb 2024 16:49:24 -0800 Subject: [PATCH 3/4] Format release targets output (#5608) ## Description Solves [1] and [2] of https://github.com/FuelLabs/sway/issues/5607 fuel target ![image](https://github.com/FuelLabs/sway/assets/47993817/44e4a877-919d-4046-8095-51a5788994c8) other targets ![image](https://github.com/FuelLabs/sway/assets/47993817/069945a4-be75-4516-a720-a6a8e3c92b73) ## Checklist - [x] I have linked to any relevant issues. - [ ] I have commented my code, particularly in hard-to-understand areas. - [ ] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [ ] I have added tests that prove my fix is effective or that my feature works. - [ ] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [ ] 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). - [ ] I have requested a review from the relevant team or maintainers. --- forc-pkg/src/manifest.rs | 3 ++ forc-pkg/src/pkg.rs | 74 +++++++++++++++++++++-------------- forc-util/src/lib.rs | 2 +- sway-core/src/build_config.rs | 6 +-- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/forc-pkg/src/manifest.rs b/forc-pkg/src/manifest.rs index 255b8e57286..abcdbeffda9 100644 --- a/forc-pkg/src/manifest.rs +++ b/forc-pkg/src/manifest.rs @@ -212,6 +212,7 @@ pub struct DependencyDetails { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] #[serde(rename_all = "kebab-case")] pub struct BuildProfile { + pub name: String, #[serde(default)] pub print_ast: bool, pub print_dca_graph: Option, @@ -716,6 +717,7 @@ impl BuildProfile { pub fn debug() -> Self { Self { + name: Self::DEBUG.into(), print_ast: false, print_dca_graph: None, print_dca_graph_url_format: None, @@ -738,6 +740,7 @@ impl BuildProfile { pub fn release() -> Self { Self { + name: Self::RELEASE.to_string(), print_ast: false, print_dca_graph: None, print_dca_graph_url_format: None, diff --git a/forc-pkg/src/pkg.rs b/forc-pkg/src/pkg.rs index ba8823dc01a..cce6cca4c97 100644 --- a/forc-pkg/src/pkg.rs +++ b/forc-pkg/src/pkg.rs @@ -7,6 +7,7 @@ use crate::{ source::{self, IPFSNode, Source}, }; use anyhow::{anyhow, bail, Context, Error, Result}; +use forc_tracing::println_warning; use forc_util::{ default_output_directory, find_file_name, kebab_to_snake_case, print_compiling, print_on_failure, print_warnings, @@ -50,7 +51,7 @@ use sway_error::{error::CompileError, handler::Handler, warning::CompileWarning} use sway_types::constants::{CORE, PRELUDE, STD}; use sway_types::{Ident, Span, Spanned}; use sway_utils::{constants, time_expr, PerformanceData, PerformanceMetric}; -use tracing::{info, warn}; +use tracing::{debug, info, warn}; type GraphIx = u32; type Node = Pinned; @@ -492,7 +493,7 @@ impl BuiltPackage { let json_abi_path = output_dir.join(program_abi_stem).with_extension("json"); self.write_json_abi(&json_abi_path, minify.clone())?; - info!(" Bytecode size: {} bytes", self.bytecode.bytes.len()); + debug!(" Bytecode size: {} bytes", self.bytecode.bytes.len()); // Additional ops required depending on the program type match self.tree_type { TreeType::Contract => { @@ -2036,52 +2037,50 @@ pub const SWAY_BIN_ROOT_SUFFIX: &str = "-bin-root"; fn build_profile_from_opts( build_profiles: &HashMap, build_options: &BuildOpts, -) -> Result<(String, BuildProfile)> { +) -> Result { let BuildOpts { pkg, print, + time_phases, build_profile, release, - time_phases, metrics_outfile, tests, error_on_warnings, experimental, .. } = build_options; - let mut selected_build_profile = BuildProfile::DEBUG; - match &build_profile { - Some(build_profile) => { - if *release { - warn!( - "You specified both {} and 'release' profiles. Using the 'release' profile", + let selected_profile_name = match &build_profile { + Some(build_profile) => match release { + true => { + println_warning(&format!( + "Both {} and 'release' profiles were specified. Using the 'release' profile", build_profile - ); - selected_build_profile = BuildProfile::RELEASE; - } else { - selected_build_profile = build_profile; + )); + BuildProfile::RELEASE } - } - None => { - if *release { - selected_build_profile = BuildProfile::RELEASE; - } - } - } + false => build_profile, + }, + None => match release { + true => BuildProfile::RELEASE, + false => BuildProfile::DEBUG, + }, + }; // Retrieve the specified build profile let mut profile = build_profiles - .get(selected_build_profile) + .get(selected_profile_name) .cloned() .unwrap_or_else(|| { warn!( "provided profile option {} is not present in the manifest file. \ Using default profile.", - selected_build_profile + selected_profile_name ); Default::default() }); + profile.name = selected_profile_name.into(); profile.print_ast |= print.ast; if profile.print_dca_graph.is_none() { profile.print_dca_graph = print.dca_graph.clone(); @@ -2102,7 +2101,18 @@ fn build_profile_from_opts( profile.error_on_warnings |= error_on_warnings; profile.experimental = experimental.clone(); - Ok((selected_build_profile.to_string(), profile)) + Ok(profile) +} + +/// Returns a formatted string of the selected build profile and targets. +fn profile_target_string(profile_name: &str, build_target: &BuildTarget) -> String { + let mut targets = vec![format!("{build_target}")]; + match profile_name { + BuildProfile::DEBUG => targets.insert(0, "unoptimized".into()), + BuildProfile::RELEASE => targets.insert(0, "optimized".into()), + _ => {} + }; + format!("{profile_name} [{}] target(s)", targets.join(" + ")) } /// Check if the given node is a contract dependency of any node in the graph. @@ -2143,7 +2153,7 @@ pub fn build_with_options(build_options: BuildOpts) -> Result { .find(|&pkg_manifest| pkg_manifest.dir() == path); let build_profiles: HashMap = build_plan.build_profiles().collect(); // Get the selected build profile using build options - let (profile_name, build_profile) = build_profile_from_opts(&build_profiles, &build_options)?; + let build_profile = build_profile_from_opts(&build_profiles, &build_options)?; // If this is a workspace we want to have all members in the output. let outputs = match curr_manifest { Some(pkg_manifest) => std::iter::once( @@ -2164,16 +2174,20 @@ pub fn build_with_options(build_options: BuildOpts) -> Result { let output_dir = pkg.output_directory.as_ref().map(PathBuf::from); let finished = ansi_term::Colour::Green.bold().paint("Finished"); - info!(" {finished} {profile_name} in {:?}", build_start.elapsed()); + info!( + " {finished} {} in {:.2}s", + profile_target_string(&build_profile.name, build_target), + build_start.elapsed().as_secs_f32() + ); for (node_ix, built_package) in built_packages.into_iter() { print_pkg_summary_header(&built_package); let pinned = &graph[node_ix]; let pkg_manifest = manifest_map .get(&pinned.id()) .ok_or_else(|| anyhow!("Couldn't find member manifest for {}", pinned.name))?; - let output_dir = output_dir - .clone() - .unwrap_or_else(|| default_output_directory(pkg_manifest.dir()).join(&profile_name)); + let output_dir = output_dir.clone().unwrap_or_else(|| { + default_output_directory(pkg_manifest.dir()).join(&build_profile.name) + }); // Output artifacts for the built package if let Some(outfile) = &binary_outfile { built_package.write_bytecode(outfile.as_ref())?; @@ -2208,7 +2222,7 @@ fn print_pkg_summary_header(built_pkg: &BuiltPackage) { let name_ansi = ansi_term::Style::new() .bold() .paint(&built_pkg.descriptor.name); - info!("{padding}{ty_ansi} {name_ansi}"); + debug!("{padding}{ty_ansi} {name_ansi}"); } /// Returns the ContractId of a built_package contract with specified `salt`. diff --git a/forc-util/src/lib.rs b/forc-util/src/lib.rs index aa6b58a6326..c23181e9d32 100644 --- a/forc-util/src/lib.rs +++ b/forc-util/src/lib.rs @@ -353,7 +353,7 @@ pub fn print_compiling(ty: Option<&TreeType>, name: &str, src: &dyn std::fmt::Di Some(ty) => format!("{} ", program_type_str(ty)), None => "".to_string(), }; - tracing::info!( + tracing::debug!( " {} {ty}{} ({src})", Colour::Green.bold().paint("Compiling"), ansi_term::Style::new().bold().paint(name) diff --git a/sway-core/src/build_config.rs b/sway-core/src/build_config.rs index efe9251ce59..0cfbaa4ba14 100644 --- a/sway-core/src/build_config.rs +++ b/sway-core/src/build_config.rs @@ -1,12 +1,12 @@ -use std::{path::PathBuf, sync::Arc}; - use serde::{Deserialize, Serialize}; -use strum::EnumString; +use std::{path::PathBuf, sync::Arc}; +use strum::{Display, EnumString}; #[derive( Clone, Copy, Debug, + Display, Default, Eq, PartialEq, From 65c19271070ade67d989e8d220f44f00bfa49e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Matos?= Date: Wed, 14 Feb 2024 14:59:18 +0000 Subject: [PATCH 4/4] Introduce lexical scopes to namespace modules (#5600) ## Description This PR introduces a hierarchy of lexical scopes to namespace modules. This might still have some bugs to work out, but I don't expect the API to need to change, so am offloading this right now to be able to unblock further work we have pending on namespaces/modules. ## 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. --- sway-core/src/ir_generation/compile.rs | 4 +- sway-core/src/ir_generation/const_eval.rs | 12 +- sway-core/src/language/call_path.rs | 7 +- .../ast_node/declaration/abi.rs | 26 ++-- .../ast_node/declaration/auto_impl.rs | 2 +- .../ast_node/declaration/declaration.rs | 2 +- .../function/function_parameter.rs | 42 +++--- .../ast_node/declaration/impl_trait.rs | 2 +- .../ast_node/declaration/trait.rs | 26 ++-- .../ast_node/expression/typed_expression.rs | 28 ++-- .../typed_expression/struct_instantiation.rs | 2 +- .../namespace/{items.rs => lexical_scope.rs} | 20 +++ .../src/semantic_analysis/namespace/mod.rs | 4 +- .../src/semantic_analysis/namespace/module.rs | 124 ++++++++++++------ .../semantic_analysis/namespace/namespace.rs | 8 +- .../semantic_analysis/type_check_context.rs | 29 ++-- .../ast_elements/type_parameter.rs | 40 +++--- sway-core/src/type_system/id.rs | 2 +- .../capabilities/hover/hover_link_contents.rs | 6 +- sway-lsp/src/core/session.rs | 2 +- sway-lsp/src/traverse/typed_tree.rs | 16 ++- 21 files changed, 250 insertions(+), 154 deletions(-) rename sway-core/src/semantic_analysis/namespace/{items.rs => lexical_scope.rs} (95%) diff --git a/sway-core/src/ir_generation/compile.rs b/sway-core/src/ir_generation/compile.rs index 2016f04d881..4c46b8d4095 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.items().get_all_declared_symbols() { + for decl_name in module_ns.current_items().get_all_declared_symbols() { if let Some(ty::TyDecl::ConstantDecl(ty::ConstantDecl { decl_id, .. })) = - module_ns.items().symbols.get(decl_name) + module_ns.current_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 dc49ddeeb32..0fad3ec685d 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.items().check_symbol(&call_path.suffix); + let decl = module_ns.current_items().check_symbol(&call_path.suffix); let const_decl = match const_decl { Some(decl) => Some(decl), None => None, @@ -1179,10 +1179,12 @@ mod tests { let handler = Handler::default(); let mut context = Context::new(engines.se(), sway_ir::ExperimentalFlags::default()); let mut md_mgr = MetadataManager::default(); - let mut core_lib = namespace::Module::default(); - core_lib.name = Some(sway_types::Ident::new_no_span( - "assert_is_constant_test".to_string(), - )); + let core_lib = namespace::Module { + name: Some(sway_types::Ident::new_no_span( + "assert_is_constant_test".to_string(), + )), + ..Default::default() + }; let r = crate::compile_to_ast( &handler, diff --git a/sway-core/src/language/call_path.rs b/sway-core/src/language/call_path.rs index feaf04e5d61..d19c5c404ed 100644 --- a/sway-core/src/language/call_path.rs +++ b/sway-core/src/language/call_path.rs @@ -313,7 +313,12 @@ impl CallPath { let mut is_external = false; let mut is_absolute = false; - if let Some(use_synonym) = namespace.module().items().use_synonyms.get(&self.suffix) { + if let Some(use_synonym) = namespace + .module() + .current_items() + .use_synonyms + .get(&self.suffix) + { synonym_prefixes = use_synonym.0.clone(); is_absolute = use_synonym.3; let submodule = namespace.module().submodule(&[use_synonym.0[0].clone()]); 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 b4887a16c39..d07cfcb5c12 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs @@ -302,17 +302,21 @@ 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.module_mut().items_mut().insert_symbol( - handler, - const_name.clone(), - ty::TyDecl::ConstantDecl(ty::ConstantDecl { - name: const_name, - decl_id: *decl_ref.id(), - decl_span: const_decl.span.clone(), - }), - const_shadowing_mode, - generic_shadowing_mode, - ); + let _ = ctx + .namespace + .module_mut() + .current_items_mut() + .insert_symbol( + handler, + const_name.clone(), + ty::TyDecl::ConstantDecl(ty::ConstantDecl { + name: const_name, + decl_id: *decl_ref.id(), + decl_span: const_decl.span.clone(), + }), + const_shadowing_mode, + generic_shadowing_mode, + ); } ty::TyTraitInterfaceItem::Type(decl_ref) => { all_items.push(TyImplItem::Type(decl_ref.clone())); 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 865d49d4f5d..b029a326b8c 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 @@ -532,7 +532,7 @@ impl<'a, 'b> AutoImplAbiEncodeContext<'a, 'b> { self.ctx .namespace .module_mut() - .items_mut() + .current_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 558579d574b..15a260aeda2 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs @@ -363,7 +363,7 @@ impl TyDecl { // declarations are not allowed ctx.namespace .module_mut() - .items_mut() + .current_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 9cc2e048371..33e52dd376d 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,25 +105,29 @@ 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.module_mut().items_mut().insert_symbol( - handler, - self.name.clone(), - ty::TyDecl::VariableDecl(Box::new(ty::TyVariableDecl { - name: self.name.clone(), - body: ty::TyExpression { - expression: ty::TyExpressionVariant::FunctionParameter, + let _ = ctx + .namespace + .module_mut() + .current_items_mut() + .insert_symbol( + handler, + self.name.clone(), + ty::TyDecl::VariableDecl(Box::new(ty::TyVariableDecl { + name: self.name.clone(), + body: ty::TyExpression { + expression: ty::TyExpressionVariant::FunctionParameter, + return_type: self.type_argument.type_id, + span: self.name.span(), + }, + mutability: ty::VariableMutability::new_from_ref_mut( + self.is_reference, + self.is_mutable, + ), return_type: self.type_argument.type_id, - span: self.name.span(), - }, - mutability: ty::VariableMutability::new_from_ref_mut( - self.is_reference, - self.is_mutable, - ), - return_type: self.type_argument.type_id, - type_ascription: self.type_argument.clone(), - })), - const_shadowing_mode, - generic_shadowing_mode, - ); + type_ascription: self.type_argument.clone(), + })), + const_shadowing_mode, + generic_shadowing_mode, + ); } } 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 5c698deed17..55fb667ad64 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 @@ -631,7 +631,7 @@ fn type_check_trait_implementation( // supertraits of this trait. ctx.namespace .module_mut() - .items_mut() + .current_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 6e557087871..c5ec376778b 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs @@ -447,17 +447,21 @@ 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.module_mut().items_mut().insert_symbol( - handler, - const_name.clone(), - ty::TyDecl::ConstantDecl(ty::ConstantDecl { - name: const_name, - decl_id: *decl_ref.id(), - decl_span: const_decl.span.clone(), - }), - const_shadowing_mode, - generic_shadowing_mode, - ); + let _ = ctx + .namespace + .module_mut() + .current_items_mut() + .insert_symbol( + handler, + const_name.clone(), + ty::TyDecl::ConstantDecl(ty::ConstantDecl { + name: const_name, + decl_id: *decl_ref.id(), + decl_span: const_decl.span.clone(), + }), + const_shadowing_mode, + generic_shadowing_mode, + ); } ty::TyTraitInterfaceItem::Type(decl_ref) => { all_items.push(TyImplItem::Type(decl_ref.clone())); 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 304103337fe..cca657c3d4c 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 @@ -1027,25 +1027,31 @@ impl ty::TyExpression { let decl_engine = ctx.engines.de(); let engines = ctx.engines(); - if !ctx.namespace.module().items().has_storage_declared() { + if !ctx + .namespace + .module() + .current_items() + .has_storage_declared() + { return Err(handler.emit_err(CompileError::NoDeclaredStorage { span: span.clone() })); } let storage_fields = ctx .namespace .module() - .items() + .current_items() .get_storage_field_descriptors(handler, decl_engine)?; // Do all namespace checking here! - let (storage_access, mut access_type) = ctx.namespace.module().items().apply_storage_load( - handler, - ctx.engines, - ctx.namespace, - checkee, - &storage_fields, - storage_keyword_span, - )?; + let (storage_access, mut access_type) = + ctx.namespace.module().current_items().apply_storage_load( + handler, + ctx.engines, + ctx.namespace, + checkee, + &storage_fields, + storage_keyword_span, + )?; // The type of a storage access is `core::storage::StorageKey`. This is // the path to it. @@ -2030,7 +2036,7 @@ impl ty::TyExpression { }; let names_vec = names_vec.into_iter().rev().collect::>(); let (ty_of_field, _ty_of_parent) = - ctx.namespace.module().items().find_subfield_type( + ctx.namespace.module().current_items().find_subfield_type( handler, ctx.engines(), ctx.namespace, 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 666056d3e4f..33b0e8c083f 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 @@ -255,7 +255,7 @@ fn collect_struct_constructors( // that we wish to encourage. namespace .module() - .items() + .current_items() .get_items_for_type(engines, struct_type_id) .iter() .filter_map(|item| match item { diff --git a/sway-core/src/semantic_analysis/namespace/items.rs b/sway-core/src/semantic_analysis/namespace/lexical_scope.rs similarity index 95% rename from sway-core/src/semantic_analysis/namespace/items.rs rename to sway-core/src/semantic_analysis/namespace/lexical_scope.rs index 73281ebf5d4..f0665e1a670 100644 --- a/sway-core/src/semantic_analysis/namespace/items.rs +++ b/sway-core/src/semantic_analysis/namespace/lexical_scope.rs @@ -32,6 +32,26 @@ pub(super) type SymbolMap = im::OrdMap; pub(super) type UseSynonyms = im::HashMap, GlobImport, ty::TyDecl, bool)>; pub(super) type UseAliases = im::HashMap; +/// Represents a lexical scope integer-based identifier, which can be used to reference +/// specific a lexical scope. +pub type LexicalScopeId = usize; + +/// Represents a lexical scope path, a vector of lexical scope identifiers, which specifies +/// the path from root to a specific lexical scope in the hierarchy. +pub type LexicalScopePath = Vec; + +/// A `LexicalScope` contains a set of all items that exist within the lexical scope via declaration or +/// importing, along with all its associated hierarchical scopes. +#[derive(Clone, Debug, Default)] +pub struct LexicalScope { + /// The set of symbols, implementations, synonyms and aliases present within this scope. + pub items: Items, + /// The set of available scopes defined inside this scope's hierarchy. + pub children: Vec, + /// The parent scope associated with this scope. Will be None for a root scope. + pub parent: Option, +} + /// The set of items that exist within some lexical scope via declaration or importing. #[derive(Clone, Debug, Default)] pub struct Items { diff --git a/sway-core/src/semantic_analysis/namespace/mod.rs b/sway-core/src/semantic_analysis/namespace/mod.rs index c43ff29f874..bf6a1875bf7 100644 --- a/sway-core/src/semantic_analysis/namespace/mod.rs +++ b/sway-core/src/semantic_analysis/namespace/mod.rs @@ -1,4 +1,4 @@ -mod items; +mod lexical_scope; mod module; #[allow(clippy::module_inception)] mod namespace; @@ -6,7 +6,7 @@ mod root; mod submodule_namespace; mod trait_map; -pub use items::Items; +pub use lexical_scope::{Items, LexicalScope, LexicalScopeId, LexicalScopePath}; pub use module::Module; pub use namespace::Namespace; pub use namespace::TryInsertingTraitImplOnFailure; diff --git a/sway-core/src/semantic_analysis/namespace/module.rs b/sway-core/src/semantic_analysis/namespace/module.rs index aac01ab7624..15318aecda2 100644 --- a/sway-core/src/semantic_analysis/namespace/module.rs +++ b/sway-core/src/semantic_analysis/namespace/module.rs @@ -12,10 +12,10 @@ use crate::{ }; use super::{ - items::{GlobImport, Items, SymbolMap}, + lexical_scope::{GlobImport, Items, LexicalScope, SymbolMap}, root::Root, trait_map::TraitMap, - ModuleName, Path, PathBuf, + LexicalScopeId, ModuleName, Path, PathBuf, }; use sway_ast::ItemConst; @@ -43,8 +43,10 @@ pub struct Module { /// /// Note that we *require* this map to be ordered to produce deterministic codegen results. pub(crate) submodules: im::OrdMap, - /// The set of symbols, implementations, synonyms and aliases present within this module. - items: Items, + /// Keeps all lexical scopes associated with this module. + pub lexical_scopes: Vec, + /// Current lexical scope id in the lexical scope hierarchy stack. + pub current_lexical_scope_id: LexicalScopeId, /// Name of the module, package name for root module, module name for other modules. /// Module name used is the same as declared in `mod name;`. pub name: Option, @@ -67,7 +69,8 @@ impl Default for Module { Self { visibility: Visibility::Private, submodules: Default::default(), - items: Default::default(), + lexical_scopes: vec![LexicalScope::default()], + current_lexical_scope_id: 0, name: Default::default(), span: Default::default(), is_external: Default::default(), @@ -176,7 +179,7 @@ impl Module { compiled_constants.insert(name, typed_decl); let mut ret = Self::default(); - ret.items.symbols = compiled_constants; + ret.current_lexical_scope_mut().items.symbols = compiled_constants; Ok(ret) } @@ -228,14 +231,54 @@ impl Module { } } - /// The collection of items declared by this module - pub fn items(&self) -> &Items { - &self.items + /// Returns the current lexical scope associated with this module. + fn current_lexical_scope(&self) -> &LexicalScope { + self.lexical_scopes + .get(self.current_lexical_scope_id) + .unwrap() } - /// The mutable collection of items declared by this module - pub fn items_mut(&mut self) -> &mut Items { - &mut self.items + /// Returns the mutable current lexical scope associated with this module. + fn current_lexical_scope_mut(&mut self) -> &mut LexicalScope { + self.lexical_scopes + .get_mut(self.current_lexical_scope_id) + .unwrap() + } + + /// The collection of items declared by this module's root lexical scope. + pub fn current_items(&self) -> &Items { + &self.current_lexical_scope().items + } + + /// The mutable collection of items declared by this module's root lexical scope. + pub fn current_items_mut(&mut self) -> &mut Items { + &mut self.current_lexical_scope_mut().items + } + + pub fn current_lexical_scope_id(&self) -> LexicalScopeId { + self.current_lexical_scope_id + } + + /// Pushes a new scope to the module's lexical scope hierarchy. + pub fn push_new_lexical_scope(&mut self) -> LexicalScopeId { + let previous_scope_id = self.current_lexical_scope_id(); + let new_scoped_id = { + self.lexical_scopes.push(LexicalScope { + parent: Some(previous_scope_id), + ..Default::default() + }); + self.current_lexical_scope_id() + }; + let previous_scope = self.lexical_scopes.get_mut(previous_scope_id).unwrap(); + previous_scope.children.push(new_scoped_id); + self.current_lexical_scope_id = new_scoped_id; + new_scoped_id + } + + /// Pops the current scope from the module's lexical scope hierarchy. + pub fn pop_lexical_scope(&mut self) { + let parent_scope_id = self.current_lexical_scope().parent; + self.current_lexical_scope_id = parent_scope_id.unwrap_or(0); } /// Given a path to a `src` module, create synonyms to every symbol in that module to the given @@ -258,9 +301,9 @@ impl Module { let src_mod = self.check_submodule(handler, src)?; - let implemented_traits = src_mod.items().implemented_traits.clone(); + let implemented_traits = src_mod.current_items().implemented_traits.clone(); let mut symbols_and_decls = vec![]; - for (symbol, decl) in src_mod.items().symbols.iter() { + for (symbol, decl) in src_mod.current_items().symbols.iter() { if is_ancestor(src, dst) || decl.visibility(decl_engine).is_public() { symbols_and_decls.push((symbol.clone(), decl.clone())); } @@ -268,11 +311,11 @@ impl Module { let dst_mod = &mut self[dst]; dst_mod - .items_mut() + .current_items_mut() .implemented_traits .extend(implemented_traits, engines); for symbol_and_decl in symbols_and_decls { - dst_mod.items_mut().use_synonyms.insert( + dst_mod.current_items_mut().use_synonyms.insert( symbol_and_decl.0, ( src.to_vec(), @@ -306,15 +349,15 @@ impl Module { let src_mod = self.check_submodule(handler, src)?; - let implemented_traits = src_mod.items().implemented_traits.clone(); - let use_synonyms = src_mod.items().use_synonyms.clone(); + let implemented_traits = src_mod.current_items().implemented_traits.clone(); + let use_synonyms = src_mod.current_items().use_synonyms.clone(); let mut symbols_and_decls = src_mod - .items() + .current_items() .use_synonyms .iter() .map(|(symbol, (_, _, decl, _))| (symbol.clone(), decl.clone())) .collect::>(); - for (symbol, decl) in src_mod.items().symbols.iter() { + for (symbol, decl) in src_mod.current_items().symbols.iter() { if is_ancestor(src, dst) || decl.visibility(decl_engine).is_public() { symbols_and_decls.push((symbol.clone(), decl.clone())); } @@ -340,13 +383,13 @@ impl Module { let dst_mod = &mut self[dst]; dst_mod - .items_mut() + .current_items_mut() .implemented_traits .extend(implemented_traits, engines); let mut try_add = |symbol, path, decl: ty::TyDecl| { dst_mod - .items_mut() + .current_items_mut() .use_synonyms .insert(symbol, (path, GlobImport::Yes, decl, is_src_absolute)); }; @@ -407,7 +450,7 @@ impl Module { let src_mod = self.check_submodule(handler, src)?; let mut impls_to_insert = TraitMap::default(); - match src_mod.items().symbols.get(item).cloned() { + match src_mod.current_items().symbols.get(item).cloned() { Some(decl) => { if !decl.visibility(decl_engine).is_public() && !is_ancestor(src, dst) { handler.emit_err(CompileError::ImportPrivateSymbol { @@ -420,7 +463,7 @@ impl Module { if let Ok(type_id) = decl.return_type(&Handler::default(), engines) { impls_to_insert.extend( src_mod - .items() + .current_items() .implemented_traits .filter_by_type_item_import(type_id, engines), engines, @@ -433,7 +476,7 @@ impl Module { // this is okay for now but we'll need to device some mechanism to collect all available trait impls impls_to_insert.extend( src_mod - .items() + .current_items() .implemented_traits .filter_by_trait_decl_span(decl_span), engines, @@ -442,11 +485,12 @@ impl Module { // no matter what, import it this way though. let dst_mod = &mut self[dst]; let add_synonym = |name| { - if let Some((_, GlobImport::No, _, _)) = dst_mod.items().use_synonyms.get(name) + if let Some((_, GlobImport::No, _, _)) = + dst_mod.current_items().use_synonyms.get(name) { handler.emit_err(CompileError::ShadowsOtherSymbol { name: name.into() }); } - dst_mod.items_mut().use_synonyms.insert( + dst_mod.current_items_mut().use_synonyms.insert( name.clone(), (src.to_vec(), GlobImport::No, decl, is_src_absolute), ); @@ -455,7 +499,7 @@ impl Module { Some(alias) => { add_synonym(&alias); dst_mod - .items_mut() + .current_items_mut() .use_aliases .insert(alias.as_str().to_string(), item.clone()); } @@ -472,7 +516,7 @@ impl Module { let dst_mod = &mut self[dst]; dst_mod - .items_mut() + .current_items_mut() .implemented_traits .extend(impls_to_insert, engines); @@ -499,7 +543,7 @@ impl Module { let decl_engine = engines.de(); let src_mod = self.check_submodule(handler, src)?; - match src_mod.items().symbols.get(enum_name).cloned() { + match src_mod.current_items().symbols.get(enum_name).cloned() { Some(decl) => { if !decl.visibility(decl_engine).is_public() && !is_ancestor(src, dst) { handler.emit_err(CompileError::ImportPrivateSymbol { @@ -528,13 +572,13 @@ impl Module { let dst_mod = &mut self[dst]; let mut add_synonym = |name| { if let Some((_, GlobImport::No, _, _)) = - dst_mod.items().use_synonyms.get(name) + dst_mod.current_items().use_synonyms.get(name) { handler.emit_err(CompileError::ShadowsOtherSymbol { name: name.into(), }); } - dst_mod.items_mut().use_synonyms.insert( + dst_mod.current_items_mut().use_synonyms.insert( name.clone(), ( src.to_vec(), @@ -552,7 +596,7 @@ impl Module { Some(alias) => { add_synonym(&alias); dst_mod - .items_mut() + .current_items_mut() .use_aliases .insert(alias.as_str().to_string(), variant_name.clone()); } @@ -599,7 +643,7 @@ impl Module { let decl_engine = engines.de(); let src_mod = self.check_submodule(handler, src)?; - match src_mod.items().symbols.get(enum_name).cloned() { + match src_mod.current_items().symbols.get(enum_name).cloned() { Some(decl) => { if !decl.visibility(decl_engine).is_public() && !is_ancestor(src, dst) { handler.emit_err(CompileError::ImportPrivateSymbol { @@ -626,7 +670,7 @@ impl Module { // import it this way. let dst_mod = &mut self[dst]; - dst_mod.items_mut().use_synonyms.insert( + dst_mod.current_items_mut().use_synonyms.insert( variant_name.clone(), ( src.to_vec(), @@ -965,7 +1009,7 @@ impl Module { type_id }; let item_ref = self - .items() + .current_items() .implemented_traits .get_trait_item_for_type(handler, engines, symbol, type_id, as_trait)?; match item_ref { @@ -985,11 +1029,11 @@ impl Module { self_type: Option, ) -> Result { let true_symbol = self[mod_path] - .items() + .current_items() .use_aliases .get(symbol.as_str()) .unwrap_or(symbol); - match module.items().use_synonyms.get(symbol) { + match module.current_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, @@ -1001,13 +1045,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.items().symbols.get(true_symbol) { + match module.current_items().symbols.get(true_symbol) { Some(decl) => Ok(decl.clone()), None => self.resolve_symbol(handler, engines, src_path, true_symbol, self_type), } } _ => module - .items() + .current_items() .check_symbol(true_symbol) .map_err(|e| handler.emit_err(e)) .cloned(), diff --git a/sway-core/src/semantic_analysis/namespace/namespace.rs b/sway-core/src/semantic_analysis/namespace/namespace.rs index 7d68e5a27d6..89d3b9bfae6 100644 --- a/sway-core/src/semantic_analysis/namespace/namespace.rs +++ b/sway-core/src/semantic_analysis/namespace/namespace.rs @@ -80,17 +80,11 @@ impl Namespace { } /// Access to the current [Module], i.e. the module at the inner `mod_path`. - /// - /// Note that the [Namespace] will automatically dereference to this [Module] when attempting - /// to call any [Module] methods. pub fn module(&self) -> &Module { &self.root.module[&self.mod_path] } /// Mutable access to the current [Module], i.e. the module at the inner `mod_path`. - /// - /// Note that the [Namespace] will automatically dereference to this [Module] when attempting - /// to call any [Module] methods. pub fn module_mut(&mut self) -> &mut Module { &mut self.root.module[&self.mod_path] } @@ -175,7 +169,7 @@ impl Namespace { ) -> Result { self.root .module - .items() + .current_items() .implemented_traits .get_trait_item_for_type(handler, engines, name, type_id, as_trait) } diff --git a/sway-core/src/semantic_analysis/type_check_context.rs b/sway-core/src/semantic_analysis/type_check_context.rs index 1df3f4b8c11..07bd60b8f7e 100644 --- a/sway-core/src/semantic_analysis/type_check_context.rs +++ b/sway-core/src/semantic_analysis/type_check_context.rs @@ -448,13 +448,16 @@ impl<'a> TypeCheckContext<'a> { name: Ident, item: TyDecl, ) -> Result<(), ErrorEmitted> { - self.namespace.module_mut().items_mut().insert_symbol( - handler, - name, - item, - self.const_shadowing_mode, - self.generic_shadowing_mode, - ) + self.namespace + .module_mut() + .current_items_mut() + .insert_symbol( + handler, + name, + item, + self.const_shadowing_mode, + self.generic_shadowing_mode, + ) } /// Get the engines needed for engine threading. @@ -947,7 +950,7 @@ impl<'a> TypeCheckContext<'a> { // grab the local items from the local module let local_items = local_module - .items() + .current_items() .get_items_for_type(self.engines, type_id); // resolve the type @@ -971,7 +974,7 @@ impl<'a> TypeCheckContext<'a> { // grab the items from where the type is declared let mut type_items = type_module - .items() + .current_items() .get_items_for_type(self.engines, type_id); let mut items = local_items; @@ -1368,7 +1371,7 @@ impl<'a> TypeCheckContext<'a> { self.namespace .module_mut() - .items_mut() + .current_items_mut() .implemented_traits .insert( handler, @@ -1404,7 +1407,7 @@ impl<'a> TypeCheckContext<'a> { self.namespace .module() - .items() + .current_items() .implemented_traits .get_items_for_type_and_trait_name_and_trait_type_arguments( self.engines, @@ -1590,7 +1593,7 @@ impl<'a> TypeCheckContext<'a> { pub(crate) fn insert_trait_implementation_for_type(&mut self, type_id: TypeId) { self.namespace .module_mut() - .items_mut() + .current_items_mut() .implemented_traits .insert_for_type(self.engines, type_id); } @@ -1615,7 +1618,7 @@ impl<'a> TypeCheckContext<'a> { self.namespace .module_mut() - .items_mut() + .current_items_mut() .implemented_traits .check_if_trait_constraints_are_satisfied_for_type( &handler, 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 f29c96cbcdf..0d20fef2c3b 100644 --- a/sway-core/src/type_system/ast_elements/type_parameter.rs +++ b/sway-core/src/type_system/ast_elements/type_parameter.rs @@ -164,20 +164,28 @@ 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.module_mut().items_mut().insert_symbol( - handler, - name_a, - type_parameter_decl.clone(), - const_shadowing_mode, - generic_shadowing_mode, - ); - let _ = ctx.namespace.module_mut().items_mut().insert_symbol( - handler, - name_b, - type_parameter_decl, - const_shadowing_mode, - generic_shadowing_mode, - ); + let _ = ctx + .namespace + .module_mut() + .current_items_mut() + .insert_symbol( + handler, + name_a, + type_parameter_decl.clone(), + const_shadowing_mode, + generic_shadowing_mode, + ); + let _ = ctx + .namespace + .module_mut() + .current_items_mut() + .insert_symbol( + handler, + name_b, + type_parameter_decl, + const_shadowing_mode, + generic_shadowing_mode, + ); } /// Type check a list of [TypeParameter] and return a new list of @@ -351,7 +359,7 @@ impl TypeParameter { if let Some(sy) = ctx .namespace .module() - .items() + .current_items() .symbols .get(&type_parameter.name_ident) { @@ -466,7 +474,7 @@ impl TypeParameter { match ctx .namespace .module_mut() - .items_mut() + .current_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 1dfbe538d6d..43ead1368a9 100644 --- a/sway-core/src/type_system/id.rs +++ b/sway-core/src/type_system/id.rs @@ -579,7 +579,7 @@ impl TypeId { let generic_trait_constraints_trait_names_and_args = ctx .namespace .module() - .items() + .current_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 e5c8001ebf1..2f83a46f74d 100644 --- a/sway-lsp/src/capabilities/hover/hover_link_contents.rs +++ b/sway-lsp/src/capabilities/hover/hover_link_contents.rs @@ -93,7 +93,7 @@ impl<'a> HoverLinkContents<'a> { let call_path = CallPath::from(trait_decl.name.clone()).to_fullpath(&namespace); let impl_spans = namespace .module() - .items() + .current_items() .get_impl_spans_for_trait_name(&call_path); self.add_implementations(&trait_decl.span(), impl_spans); } @@ -104,7 +104,7 @@ impl<'a> HoverLinkContents<'a> { if let Some(namespace) = self.session.namespace() { let impl_spans = namespace .module() - .items() + .current_items() .get_impl_spans_for_decl(self.engines, ty_decl); self.add_implementations(&ty_decl.span(), impl_spans); } @@ -115,7 +115,7 @@ impl<'a> HoverLinkContents<'a> { if let Some(namespace) = self.session.namespace() { let impl_spans = namespace .module() - .items() + .current_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 a1fff539a38..e208b0e0c52 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.module().items(), + program.root.namespace.module().current_items(), &self.engines.read(), ident_to_complete, &fn_decl, diff --git a/sway-lsp/src/traverse/typed_tree.rs b/sway-lsp/src/traverse/typed_tree.rs index 5eaf5460227..a0d43315788 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.items().symbols().get(item)) + .and_then(|module| module.current_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.items().symbols().get(&abi_name.suffix)) + .and_then(|module| module.current_items().symbols().get(&abi_name.suffix)) .and_then(|decl| decl.get_decl_ident()) { token.type_def = Some(TypeDefinition::Ident(abi_def_ident)); @@ -479,8 +479,10 @@ 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.items().get_declared_storage(ctx.engines.de()) + if let Some(storage) = ctx + .namespace + .current_items() + .get_declared_storage(ctx.engines.de()) { token.type_def = Some(TypeDefinition::Ident(storage.storage_keyword.clone())); @@ -497,7 +499,7 @@ impl Parse for ty::TyExpression { )); if let Some(storage_field) = ctx .namespace - .items() + .current_items() .get_declared_storage(ctx.engines.de()) .and_then(|storage| { storage @@ -1201,7 +1203,7 @@ fn collect_call_path_tree(ctx: &ParseContext, tree: &CallPathTree, type_arg: &Ty .submodule(&abi_call_path.call_path.prefixes) .and_then(|module| { module - .items() + .current_items() .symbols() .get(&abi_call_path.call_path.suffix) }) @@ -1382,7 +1384,7 @@ fn collect_trait_constraint( if let Some(trait_def_ident) = ctx .namespace .submodule(&trait_name.prefixes) - .and_then(|module| module.items().symbols().get(&trait_name.suffix)) + .and_then(|module| module.current_items().symbols().get(&trait_name.suffix)) .and_then(|decl| decl.get_decl_ident()) { token.type_def = Some(TypeDefinition::Ident(trait_def_ident));