From 3fcd91fdbb0996600d42612495249d2d4145a11c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Thu, 28 May 2026 18:43:25 -0400 Subject: [PATCH 1/5] Cache linearised collection of contract's function, variables, etc --- .../cargo/ast/generated/public_api.txt | 10 +- .../node_extensions/contract_definition.rs | 10 +- .../node_extensions/contract_definition.rs | 107 +++----- .../node_extensions/function_definition.rs | 39 --- .../node_extensions/interface_definition.rs | 23 -- .../cargo/ast/src/ast/node_extensions/mod.rs | 2 - .../cargo/semantic/generated/public_api.txt | 5 + .../src/context/contract_data_cache.rs | 245 ++++++++++++++++++ .../outputs/cargo/semantic/src/context/mod.rs | 57 +++- .../slang_solidity/generated/public_api.txt | 1 + .../slang_solidity/src/compilation/unit.rs | 8 + .../src/tests/abi/internal_signature.rs | 8 +- .../slang_solidity/src/tests/abi/selectors.rs | 4 +- .../src/tests/ast/linearisations.rs | 8 +- 14 files changed, 354 insertions(+), 173 deletions(-) delete mode 100644 crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/function_definition.rs delete mode 100644 crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/interface_definition.rs create mode 100644 crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data_cache.rs diff --git a/crates/solidity-v2/outputs/cargo/ast/generated/public_api.txt b/crates/solidity-v2/outputs/cargo/ast/generated/public_api.txt index fcaa3477fc..287dc8fe4b 100644 --- a/crates/solidity-v2/outputs/cargo/ast/generated/public_api.txt +++ b/crates/solidity-v2/outputs/cargo/ast/generated/public_api.txt @@ -1443,16 +1443,16 @@ pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::references(&self) - impl slang_solidity_v2_ast::ast::ContractDefinitionStruct pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::compute_abi(&self) -> core::option::Option impl slang_solidity_v2_ast::ast::ContractDefinitionStruct -pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::compute_linearised_bases(&self) -> alloc::vec::Vec -pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::compute_linearised_errors(&self) -> alloc::vec::Vec -pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::compute_linearised_events(&self) -> alloc::vec::Vec -pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::compute_linearised_functions(&self) -> alloc::vec::Vec -pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::compute_linearised_state_variables(&self) -> alloc::vec::Vec pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::constructor(&self) -> core::option::Option pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::direct_bases(&self) -> alloc::vec::Vec pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::errors(&self) -> alloc::vec::Vec pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::events(&self) -> alloc::vec::Vec pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::functions(&self) -> alloc::vec::Vec +pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::linearised_bases(&self) -> alloc::vec::Vec +pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::linearised_errors(&self) -> alloc::vec::Vec +pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::linearised_events(&self) -> alloc::vec::Vec +pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::linearised_functions(&self) -> alloc::vec::Vec +pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::linearised_state_variables(&self) -> alloc::vec::Vec pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::modifiers(&self) -> alloc::vec::Vec pub fn slang_solidity_v2_ast::ast::ContractDefinitionStruct::state_variables(&self) -> alloc::vec::Vec impl serde_core::ser::Serialize for slang_solidity_v2_ast::ast::ContractDefinitionStruct diff --git a/crates/solidity-v2/outputs/cargo/ast/src/abi/node_extensions/contract_definition.rs b/crates/solidity-v2/outputs/cargo/ast/src/abi/node_extensions/contract_definition.rs index d5a1eb2f6d..f42137a021 100644 --- a/crates/solidity-v2/outputs/cargo/ast/src/abi/node_extensions/contract_definition.rs +++ b/crates/solidity-v2/outputs/cargo/ast/src/abi/node_extensions/contract_definition.rs @@ -26,20 +26,20 @@ impl ContractDefinitionStruct { if let Some(constructor) = self.constructor() { entries.push(constructor.compute_abi_entry()?); } - for function in &self.compute_linearised_functions() { + for function in &self.linearised_functions() { if function.is_externally_visible() { entries.push(function.compute_abi_entry()?); } } - for state_variable in &self.compute_linearised_state_variables() { + for state_variable in &self.linearised_state_variables() { if state_variable.is_externally_visible() { entries.push(state_variable.compute_abi_entry()?); } } - for error in &self.compute_linearised_errors() { + for error in &self.linearised_errors() { entries.push(error.compute_abi_entry()?); } - for event in &self.compute_linearised_events() { + for event in &self.linearised_events() { entries.push(event.compute_abi_entry()?); } @@ -63,7 +63,7 @@ impl ContractDefinitionStruct { /// Computes the layouts of both permanent and transient state variables fn compute_storage_layout(&self) -> Option<(Vec, Vec)> { - let all_state_variables = self.compute_linearised_state_variables(); + let all_state_variables = self.linearised_state_variables(); // TODO(validation) SDR[2]: it is an error if any contract in the hierarchy // other than the leaf has a custom offset layout diff --git a/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/contract_definition.rs b/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/contract_definition.rs index f82fc647e3..0e0e11b35a 100644 --- a/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/contract_definition.rs +++ b/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/contract_definition.rs @@ -1,5 +1,7 @@ -use std::cmp::Ordering; - +use super::super::nodes::{ + create_error_definition, create_event_definition, create_function_definition, + create_state_variable_definition, +}; use super::super::{ ContractDefinitionStruct, Definition, ErrorDefinition, EventDefinition, FunctionDefinition, FunctionKind, StateVariableDefinition, @@ -20,7 +22,7 @@ impl ContractDefinitionStruct { /// Returns the list of contracts/interfaces in the hierarchy (including /// self) in the order given by the C3 linearisation, with self contract /// always first - pub fn compute_linearised_bases(&self) -> Vec { + pub fn linearised_bases(&self) -> Vec { let Some(base_node_ids) = self .semantic .binder() @@ -47,16 +49,12 @@ impl ContractDefinitionStruct { } /// Returns the list of state variable definitions in the order laid out in storage - pub fn compute_linearised_state_variables(&self) -> Vec { - let mut state_variables = Vec::new(); - let bases = self.compute_linearised_bases(); - for base in bases.iter().rev() { - let ContractBase::Contract(contract) = base else { - continue; - }; - state_variables.extend(contract.members().iter_state_variable_definitions()); - } - state_variables + pub fn linearised_state_variables(&self) -> Vec { + self.semantic + .linearised_state_variables(self.ir_node.id()) + .iter() + .map(|ir_node| create_state_variable_definition(ir_node, &self.semantic)) + .collect() } pub fn functions(&self) -> Vec { @@ -86,82 +84,35 @@ impl ContractDefinitionStruct { /// Returns the list of functions defined in all the hierarchy of the /// contract, in alphabetical order - pub fn compute_linearised_functions(&self) -> Vec { - let mut functions: Vec = Vec::new(); - let bases = self.compute_linearised_bases(); - for base in &bases { - // TODO(validation) SDR[3]: we don't pick up functions defined in - // interfaces because they should be implemented in inheriting - // contracts, but this is not yet enforced anywhere - let ContractBase::Contract(contract) = base else { - continue; - }; - - // Handle function overriding - let contract_functions = contract - .functions() - .into_iter() - .filter(|function| { - // check the existing functions and remove any duplicates - // because they should be overridden by them - let existing = functions - .iter() - .any(|linearised_function| linearised_function.overrides(function)); - !existing - }) - // collect to avoid holding the read-borrow on `functions` - .collect::>(); - - functions.extend(contract_functions); - } - - // sort returned functions by name - functions.sort_by(|a, b| match (a.name(), b.name()) { - (None, None) => Ordering::Equal, - (None, Some(_)) => Ordering::Less, - (Some(_), None) => Ordering::Greater, - (Some(a), Some(b)) => a.name().cmp(&b.name()), - }); - functions + pub fn linearised_functions(&self) -> Vec { + self.semantic + .linearised_functions(self.ir_node.id()) + .iter() + .map(|ir_node| create_function_definition(ir_node, &self.semantic)) + .collect() } pub fn errors(&self) -> Vec { self.members().iter_error_definitions().collect() } - pub fn compute_linearised_errors(&self) -> Vec { - let mut errors = Vec::new(); - let bases = self.compute_linearised_bases(); - for base in bases.iter().rev() { - match base { - ContractBase::Contract(contract) => { - errors.extend(contract.members().iter_error_definitions()); - } - ContractBase::Interface(interface) => { - errors.extend(interface.members().iter_error_definitions()); - } - } - } - errors + pub fn linearised_errors(&self) -> Vec { + self.semantic + .linearised_errors(self.ir_node.id()) + .iter() + .map(|ir_node| create_error_definition(ir_node, &self.semantic)) + .collect() } pub fn events(&self) -> Vec { self.members().iter_event_definitions().collect() } - pub fn compute_linearised_events(&self) -> Vec { - let mut events = Vec::new(); - let bases = self.compute_linearised_bases(); - for base in bases.iter().rev() { - match base { - ContractBase::Contract(contract) => { - events.extend(contract.members().iter_event_definitions()); - } - ContractBase::Interface(interface) => { - events.extend(interface.members().iter_event_definitions()); - } - } - } - events + pub fn linearised_events(&self) -> Vec { + self.semantic + .linearised_events(self.ir_node.id()) + .iter() + .map(|ir_node| create_event_definition(ir_node, &self.semantic)) + .collect() } } diff --git a/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/function_definition.rs b/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/function_definition.rs deleted file mode 100644 index 11f1a1ef78..0000000000 --- a/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/function_definition.rs +++ /dev/null @@ -1,39 +0,0 @@ -use super::super::{FunctionDefinition, FunctionDefinitionStruct}; - -impl FunctionDefinitionStruct { - pub(crate) fn overrides(&self, other: &FunctionDefinition) -> bool { - let name_matches = match (&self.ir_node.name, &other.ir_node.name) { - (None, None) => { - // for unnamed functions, we check the kind because `receive` - // and `fallback` may have the same parameters but they are - // different functions - self.ir_node.kind == other.ir_node.kind - } - (Some(name), Some(other_name)) => name.unparse() == other_name.unparse(), - _ => false, - }; - if !name_matches { - return false; - } - let type_id = self - .semantic - .binder() - .node_typing(self.ir_node.id()) - .as_type_id(); - let other_type_id = self - .semantic - .binder() - .node_typing(other.ir_node.id()) - .as_type_id(); - - match (type_id, other_type_id) { - (Some(type_id), Some(other_type_id)) => self - .semantic - .types() - .type_id_is_function_and_overrides(type_id, other_type_id), - _ => false, - } - - // TODO(validation) SDR[6]: check also that the function mutability is stricter than other's - } -} diff --git a/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/interface_definition.rs b/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/interface_definition.rs deleted file mode 100644 index 9229d87ec6..0000000000 --- a/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/interface_definition.rs +++ /dev/null @@ -1,23 +0,0 @@ -use super::super::{ContractMember, ErrorDefinition, EventDefinition, InterfaceMembersStruct}; - -impl InterfaceMembersStruct { - pub(crate) fn iter_error_definitions(&self) -> impl Iterator + use<'_> { - self.iter().filter_map(|member| { - if let ContractMember::ErrorDefinition(error_definition) = member { - Some(error_definition) - } else { - None - } - }) - } - - pub(crate) fn iter_event_definitions(&self) -> impl Iterator + use<'_> { - self.iter().filter_map(|member| { - if let ContractMember::EventDefinition(event_definition) = member { - Some(event_definition) - } else { - None - } - }) - } -} diff --git a/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/mod.rs b/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/mod.rs index 59b273dc50..2f012d89b4 100644 --- a/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/mod.rs +++ b/crates/solidity-v2/outputs/cargo/ast/src/ast/node_extensions/mod.rs @@ -5,12 +5,10 @@ mod contract_definition; mod contract_members; mod decimal_number_expression; mod hex_number_expression; -mod interface_definition; pub use contract_base::ContractBase; mod expression; mod function_call_expression; -mod function_definition; mod identifier; mod identifier_path; mod source_unit; diff --git a/crates/solidity-v2/outputs/cargo/semantic/generated/public_api.txt b/crates/solidity-v2/outputs/cargo/semantic/generated/public_api.txt index 86abf75960..12bf9bff4e 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/generated/public_api.txt +++ b/crates/solidity-v2/outputs/cargo/semantic/generated/public_api.txt @@ -263,12 +263,17 @@ pub struct slang_solidity_v2_semantic::context::SemanticContext impl slang_solidity_v2_semantic::context::SemanticContext pub const slang_solidity_v2_semantic::context::SemanticContext::SLOT_SIZE: usize pub fn slang_solidity_v2_semantic::context::SemanticContext::file_id_from_node_id(&self, node_id: slang_solidity_v2_common::nodes::NodeId) -> &str +pub fn slang_solidity_v2_semantic::context::SemanticContext::linearised_errors(&self, contract_id: slang_solidity_v2_common::nodes::NodeId) -> &[slang_solidity_v2_ir::ir::nodes::ErrorDefinition] +pub fn slang_solidity_v2_semantic::context::SemanticContext::linearised_events(&self, contract_id: slang_solidity_v2_common::nodes::NodeId) -> &[slang_solidity_v2_ir::ir::nodes::EventDefinition] +pub fn slang_solidity_v2_semantic::context::SemanticContext::linearised_functions(&self, contract_id: slang_solidity_v2_common::nodes::NodeId) -> &[slang_solidity_v2_ir::ir::nodes::FunctionDefinition] +pub fn slang_solidity_v2_semantic::context::SemanticContext::linearised_state_variables(&self, contract_id: slang_solidity_v2_common::nodes::NodeId) -> &[slang_solidity_v2_ir::ir::nodes::StateVariableDefinition] pub fn slang_solidity_v2_semantic::context::SemanticContext::resolve_reference_identifier_to_definition_id(&self, node_id: slang_solidity_v2_common::nodes::NodeId) -> core::option::Option pub fn slang_solidity_v2_semantic::context::SemanticContext::resolve_reference_identifier_to_immediate_definition_id(&self, node_id: slang_solidity_v2_common::nodes::NodeId) -> core::option::Option pub fn slang_solidity_v2_semantic::context::SemanticContext::storage_size_of_type_id(&self, type_id: slang_solidity_v2_semantic::types::TypeId) -> core::option::Option pub fn slang_solidity_v2_semantic::context::SemanticContext::type_canonical_name(&self, type_id: slang_solidity_v2_semantic::types::TypeId) -> core::option::Option pub fn slang_solidity_v2_semantic::context::SemanticContext::type_internal_name(&self, type_id: slang_solidity_v2_semantic::types::TypeId) -> alloc::string::String impl slang_solidity_v2_semantic::context::SemanticContext +pub fn slang_solidity_v2_semantic::context::SemanticContext::all_contracts(&self) -> impl core::iter::traits::iterator::Iterator + use<'_> pub fn slang_solidity_v2_semantic::context::SemanticContext::all_definitions(&self) -> impl core::iter::traits::iterator::Iterator + use<'_> pub fn slang_solidity_v2_semantic::context::SemanticContext::all_references(&self) -> impl core::iter::traits::iterator::Iterator + use<'_> pub fn slang_solidity_v2_semantic::context::SemanticContext::binder(&self) -> &slang_solidity_v2_semantic::binder::Binder diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data_cache.rs b/crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data_cache.rs new file mode 100644 index 0000000000..4f7c2a823d --- /dev/null +++ b/crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data_cache.rs @@ -0,0 +1,245 @@ +use std::cmp::Ordering; +use std::collections::HashMap; +use std::sync::Arc; + +use slang_solidity_v2_common::nodes::NodeId; +use slang_solidity_v2_ir::ir; + +use crate::binder::{Binder, Definition}; +use crate::types::TypeRegistry; + +/// Pre-computed derived data for a single contract. +#[allow(clippy::struct_field_names)] +struct ContractData { + linearised_functions: Vec, + linearised_state_variables: Vec, + linearised_errors: Vec, + linearised_events: Vec, +} + +/// Cache of derived data about contracts, computed once at the end of the +/// semantic passes and stored on the `SemanticContext`. Every contract's +/// `NodeId` has an entry in `data`. +pub(super) struct ContractDataCache { + /// All contract definitions in this compilation unit, in registration + /// order (deterministic iteration for `all_contracts`). + contracts: Vec, + /// Lookup by simple name. Picks one definition arbitrarily if multiple + /// contracts share the same name across files. + contract_by_name: HashMap, + /// Per-contract derived data, keyed by contract `NodeId`. + data: HashMap, +} + +impl ContractDataCache { + pub(super) fn build_from(binder: &Binder, types: &TypeRegistry) -> Self { + let mut contracts = Vec::new(); + let mut contract_by_name = HashMap::new(); + let mut data = HashMap::new(); + + for (contract_id, definition) in binder.definitions() { + let Definition::Contract(contract) = definition else { + continue; + }; + let contract_id = *contract_id; + let ir_node = Arc::clone(&contract.ir_node); + let name = contract.ir_node.name.unparse().to_string(); + + let linearised_functions = compute_linearised_functions(binder, types, contract_id); + let linearised_state_variables = + collect_linearised_state_variables(binder, contract_id); + let linearised_errors = collect_linearised_errors(binder, contract_id); + let linearised_events = collect_linearised_events(binder, contract_id); + + data.insert( + contract_id, + ContractData { + linearised_functions, + linearised_state_variables, + linearised_errors, + linearised_events, + }, + ); + + contract_by_name.insert(name, Arc::clone(&ir_node)); + contracts.push(ir_node); + } + + Self { + contracts, + contract_by_name, + data, + } + } + + fn get(&self, contract_id: NodeId) -> &ContractData { + self.data + .get(&contract_id) + .expect("contract_id is a registered contract") + } + + pub(super) fn all_contracts(&self) -> impl Iterator { + self.contracts.iter() + } + + pub(super) fn find_contract_by_name(&self, name: &str) -> Option<&ir::ContractDefinition> { + self.contract_by_name.get(name) + } + + pub(super) fn linearised_functions(&self, contract_id: NodeId) -> &[ir::FunctionDefinition] { + &self.get(contract_id).linearised_functions + } + + pub(super) fn linearised_state_variables( + &self, + contract_id: NodeId, + ) -> &[ir::StateVariableDefinition] { + &self.get(contract_id).linearised_state_variables + } + + pub(super) fn linearised_errors(&self, contract_id: NodeId) -> &[ir::ErrorDefinition] { + &self.get(contract_id).linearised_errors + } + + pub(super) fn linearised_events(&self, contract_id: NodeId) -> &[ir::EventDefinition] { + &self.get(contract_id).linearised_events + } +} + +fn compute_linearised_functions( + binder: &Binder, + types: &TypeRegistry, + contract_id: NodeId, +) -> Vec { + let Some(linearised_bases) = binder.get_linearised_bases(contract_id) else { + return Vec::new(); + }; + + let mut functions: Vec = Vec::new(); + for base_id in linearised_bases { + // TODO(validation) SDR[3]: we don't pick up functions defined in + // interfaces because they should be implemented in inheriting contracts, + // but this is not yet enforced anywhere. + let Some(Definition::Contract(base)) = binder.find_definition_by_id(*base_id) else { + continue; + }; + + for member in &base.ir_node.members { + let ir::ContractMember::FunctionDefinition(function) = member else { + continue; + }; + if !matches!( + function.kind, + ir::FunctionKind::Regular | ir::FunctionKind::Fallback | ir::FunctionKind::Receive + ) { + continue; + } + let overridden = functions + .iter() + .any(|existing| function_overrides(binder, types, existing, function)); + if !overridden { + functions.push(Arc::clone(function)); + } + } + } + + functions.sort_by(|a, b| match (&a.name, &b.name) { + (None, None) => Ordering::Equal, + (None, Some(_)) => Ordering::Less, + (Some(_), None) => Ordering::Greater, + (Some(a), Some(b)) => a.unparse().cmp(b.unparse()), + }); + functions +} + +fn function_overrides( + binder: &Binder, + types: &TypeRegistry, + function: &ir::FunctionDefinition, + other: &ir::FunctionDefinition, +) -> bool { + let name_matches = match (&function.name, &other.name) { + (None, None) => function.kind == other.kind, + (Some(name), Some(other_name)) => name.unparse() == other_name.unparse(), + _ => false, + }; + if !name_matches { + return false; + } + let type_id = binder.node_typing(function.id()).as_type_id(); + let other_type_id = binder.node_typing(other.id()).as_type_id(); + match (type_id, other_type_id) { + (Some(type_id), Some(other_type_id)) => { + types.type_id_is_function_and_overrides(type_id, other_type_id) + } + _ => false, + } +} + +/// Walks the linearised bases in reverse (most-base first) and concatenates +/// every contract's state-variable members in source order. Interfaces don't +/// contribute state variables in Solidity. +fn collect_linearised_state_variables( + binder: &Binder, + contract_id: NodeId, +) -> Vec { + let mut state_variables = Vec::new(); + let Some(linearised_bases) = binder.get_linearised_bases(contract_id) else { + return state_variables; + }; + for base_id in linearised_bases.iter().rev() { + let Some(Definition::Contract(base)) = binder.find_definition_by_id(*base_id) else { + continue; + }; + for member in &base.ir_node.members { + if let ir::ContractMember::StateVariableDefinition(state_variable) = member { + state_variables.push(Arc::clone(state_variable)); + } + } + } + state_variables +} + +/// Walks the linearised bases in reverse and concatenates every contract / +/// interface error definition. +fn collect_linearised_errors(binder: &Binder, contract_id: NodeId) -> Vec { + let mut errors = Vec::new(); + let Some(linearised_bases) = binder.get_linearised_bases(contract_id) else { + return errors; + }; + for base_id in linearised_bases.iter().rev() { + let members = match binder.find_definition_by_id(*base_id) { + Some(Definition::Contract(base)) => &base.ir_node.members, + Some(Definition::Interface(base)) => &base.ir_node.members, + _ => continue, + }; + for member in members { + if let ir::ContractMember::ErrorDefinition(error) = member { + errors.push(Arc::clone(error)); + } + } + } + errors +} + +/// Walks the linearised bases in reverse and concatenates every contract / +/// interface event definition. +fn collect_linearised_events(binder: &Binder, contract_id: NodeId) -> Vec { + let mut events = Vec::new(); + let Some(linearised_bases) = binder.get_linearised_bases(contract_id) else { + return events; + }; + for base_id in linearised_bases.iter().rev() { + let members = match binder.find_definition_by_id(*base_id) { + Some(Definition::Contract(base)) => &base.ir_node.members, + Some(Definition::Interface(base)) => &base.ir_node.members, + _ => continue, + }; + for member in members { + if let ir::ContractMember::EventDefinition(event) = member { + events.push(Arc::clone(event)); + } + } + } + events +} diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs b/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs index 197ca36a19..bdcd45bcc6 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use std::sync::Arc; +use contract_data_cache::ContractDataCache; use file_node_mapper::FileNodeMapper; use slang_solidity_v2_common::diagnostics::DiagnosticCollection; use slang_solidity_v2_common::nodes::NodeId; @@ -18,6 +18,7 @@ use crate::types::{ TypeRegistry, UserDefinedValueType, }; +mod contract_data_cache; mod file_node_mapper; /// Trait for files that can be used as input to the semantic analysis passes. @@ -60,6 +61,7 @@ pub struct SemanticContext { binder: Binder, types: TypeRegistry, file_node_mapper: FileNodeMapper, + contract_data: ContractDataCache, } impl SemanticContext { @@ -77,11 +79,13 @@ impl SemanticContext { p4_resolve_references::run(files, &mut binder, &mut types, language_version); let file_node_mapper = FileNodeMapper::build_from(files); + let contract_data = ContractDataCache::build_from(&binder, &types); Self { binder, types, file_node_mapper, + contract_data, } } @@ -103,17 +107,14 @@ impl SemanticContext { self.binder.references().values() } + /// Iterates over every contract definition in this compilation unit, in + /// registration order. + pub fn all_contracts(&self) -> impl Iterator + use<'_> { + self.contract_data.all_contracts() + } + pub fn find_contract_by_name(&self, name: &str) -> Option { - self.binder().definitions().values().find_map(|definition| { - let Definition::Contract(contract) = definition else { - return None; - }; - if definition.identifier().unparse() == name { - Some(Arc::clone(&contract.ir_node)) - } else { - None - } - }) + self.contract_data.find_contract_by_name(name).cloned() } } @@ -122,6 +123,40 @@ impl SemanticContext { self.file_node_mapper.file_id_from_node_id(node_id) } + /// Returns the pre-computed list of functions visible in the given + /// contract's hierarchy (per C3 linearisation), with overrides resolved and + /// sorted by name. `contract_id` must be a registered contract definition. + pub fn linearised_functions(&self, contract_id: NodeId) -> &[ir::FunctionDefinition] { + self.contract_data.linearised_functions(contract_id) + } + + /// Returns the pre-computed list of state variables visible in the given + /// contract's hierarchy, in storage-layout order (most-base first, then + /// each contract's own variables). `contract_id` must be a registered + /// contract definition. + pub fn linearised_state_variables( + &self, + contract_id: NodeId, + ) -> &[ir::StateVariableDefinition] { + self.contract_data.linearised_state_variables(contract_id) + } + + /// Returns the pre-computed list of errors visible in the given contract's + /// hierarchy (including base contracts and interfaces, in reverse + /// linearisation order). `contract_id` must be a registered contract + /// definition. + pub fn linearised_errors(&self, contract_id: NodeId) -> &[ir::ErrorDefinition] { + self.contract_data.linearised_errors(contract_id) + } + + /// Returns the pre-computed list of events visible in the given contract's + /// hierarchy (including base contracts and interfaces, in reverse + /// linearisation order). `contract_id` must be a registered contract + /// definition. + pub fn linearised_events(&self, contract_id: NodeId) -> &[ir::EventDefinition] { + self.contract_data.linearised_events(contract_id) + } + pub fn resolve_reference_identifier_to_definition_id(&self, node_id: NodeId) -> Option { let reference = self .binder() diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/generated/public_api.txt b/crates/solidity-v2/outputs/cargo/slang_solidity/generated/public_api.txt index 28e73ad944..a34e8d1032 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/generated/public_api.txt +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/generated/public_api.txt @@ -20,6 +20,7 @@ pub fn slang_solidity_v2::compilation::CompilationBuilder::build(self) -> sla pub fn slang_solidity_v2::compilation::CompilationBuilder::create(language_version: slang_solidity_v2_common::versions::version::LanguageVersion, config: C) -> slang_solidity_v2::compilation::CompilationBuilder pub struct slang_solidity_v2::compilation::CompilationUnit impl slang_solidity_v2::compilation::CompilationUnit +pub fn slang_solidity_v2::compilation::CompilationUnit::all_contracts(&self) -> impl core::iter::traits::iterator::Iterator + use<'_> pub fn slang_solidity_v2::compilation::CompilationUnit::all_definitions(&self) -> impl core::iter::traits::iterator::Iterator + use<'_> pub fn slang_solidity_v2::compilation::CompilationUnit::all_references(&self) -> impl core::iter::traits::iterator::Iterator + use<'_> pub fn slang_solidity_v2::compilation::CompilationUnit::compute_contracts_abi(&self) -> alloc::vec::Vec diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/compilation/unit.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/compilation/unit.rs index 586b24c908..33afa5ad24 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/compilation/unit.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/compilation/unit.rs @@ -80,6 +80,14 @@ impl CompilationUnit { .map(|contract| ast::create_contract_definition(&contract, &self.semantic)) } + /// Iterates over every contract definition in this compilation unit, in + /// registration order. + pub fn all_contracts(&self) -> impl Iterator + use<'_> { + self.semantic + .all_contracts() + .map(|contract| ast::create_contract_definition(contract, &self.semantic)) + } + pub fn compute_contracts_abi(&self) -> Vec { self.files .values() diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/internal_signature.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/internal_signature.rs index 52e9e676eb..98b9898869 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/internal_signature.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/internal_signature.rs @@ -8,7 +8,7 @@ fn test_compute_internal_signature() { // Functions are linearised in alphabetical order, with the unnamed // `receive`/`fallback` functions sorted first. - let functions = test_contract.compute_linearised_functions(); + let functions = test_contract.linearised_functions(); assert_eq!(functions.len(), 3); assert_eq!( @@ -35,7 +35,7 @@ fn test_compute_internal_signature() { // State variables are linearised in storage layout order (bases first). // Only the public variables defines a getter with an internal signature. - let state_variables = test_contract.compute_linearised_state_variables(); + let state_variables = test_contract.linearised_state_variables(); assert_eq!(state_variables.len(), 3); assert_eq!( state_variables[0].compute_internal_signature(), @@ -48,7 +48,7 @@ fn test_compute_internal_signature() { ); // Errors and events are linearised with base contracts first. - let errors = test_contract.compute_linearised_errors(); + let errors = test_contract.linearised_errors(); assert_eq!(errors.len(), 2); assert_eq!( errors[0].compute_internal_signature(), @@ -59,7 +59,7 @@ fn test_compute_internal_signature() { Some("InsufficientBalance(uint256,uint256)".to_string()) ); - let events = test_contract.compute_linearised_events(); + let events = test_contract.linearised_events(); assert_eq!(events.len(), 2); assert_eq!( events[0].compute_internal_signature(), diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/selectors.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/selectors.rs index c62bf8a661..d64cf6dc75 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/selectors.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/selectors.rs @@ -8,7 +8,7 @@ fn test_function_selector() { .find_contract_by_name("Counter") .expect("contract can be found"); - let functions = counter.compute_linearised_functions(); + let functions = counter.linearised_functions(); assert_eq!(functions.len(), 5); // all the functions in the contract are public @@ -18,7 +18,7 @@ fn test_function_selector() { assert_eq!(functions[3].compute_selector(), Some(0x7cf5_dab0_u32)); // increment(uint256) assert_eq!(functions[4].compute_selector(), Some(0x6aa6_33b6_u32)); // isEnabled() - let state_variables = counter.compute_linearised_state_variables(); + let state_variables = counter.linearised_state_variables(); assert_eq!(state_variables.len(), 4); // for state variables, selectors only make sense for public getters diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/linearisations.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/linearisations.rs index 7b058c07e4..2e9000be49 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/linearisations.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/linearisations.rs @@ -33,7 +33,7 @@ fn test_contract_compute_linearised_bases() { let counter = unit .find_contract_by_name("Counter") .expect("can find Counter contract"); - let bases = counter.compute_linearised_bases(); + let bases = counter.linearised_bases(); assert_eq!(bases.len(), 3); let ContractBase::Contract(counter) = &bases[0] else { @@ -58,7 +58,7 @@ fn test_contract_compute_linearised_state_variables() { .find_contract_by_name("Counter") .expect("can find Counter contract"); - let state_variables = counter.compute_linearised_state_variables(); + let state_variables = counter.linearised_state_variables(); assert_eq!(state_variables.len(), 4); assert_eq!(state_variables[0].name().name(), "_owner"); @@ -75,7 +75,7 @@ fn test_contract_compute_linearised_functions() { .find_contract_by_name("Counter") .expect("can find Counter contract"); - let functions = counter.compute_linearised_functions(); + let functions = counter.linearised_functions(); assert_eq!(functions.len(), 5); assert!(functions[0] @@ -102,7 +102,7 @@ fn test_contract_compute_linearised_functions_with_overrides() { let inherited = unit .find_contract_by_name("Inherited") .expect("can find contract"); - let functions = inherited.compute_linearised_functions(); + let functions = inherited.linearised_functions(); assert_eq!(functions.len(), 3); assert!(functions[0] .name() From 78fc92d1636e459812c57b2dcb4fed3538f5bc5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Fri, 5 Jun 2026 17:50:30 -0400 Subject: [PATCH 2/5] Address PR comments; change `find_contract_by_name` to return an iterator --- .../src/context/contract_data_cache.rs | 22 ++++++++----------- .../outputs/cargo/semantic/src/context/mod.rs | 13 +++++++---- .../slang_solidity/src/compilation/unit.rs | 11 +++++++--- .../src/tests/abi/internal_signature.rs | 1 + .../slang_solidity/src/tests/abi/selectors.rs | 3 +++ .../src/tests/abi/storage_layout.rs | 4 ++++ .../src/tests/ast/definition_references.rs | 1 + .../tests/ast/identifier_path_resolution.rs | 11 ++++++++-- .../src/tests/ast/linearisations.rs | 4 ++++ .../slang_solidity/src/tests/ast/members.rs | 2 ++ .../src/tests/ast/node_location.rs | 3 +++ .../slang_solidity/src/tests/ast/typing.rs | 2 ++ .../cargo/slang_solidity/src/tests/unit.rs | 3 +++ 13 files changed, 58 insertions(+), 22 deletions(-) diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data_cache.rs b/crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data_cache.rs index 4f7c2a823d..b2652456f2 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data_cache.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data_cache.rs @@ -24,9 +24,6 @@ pub(super) struct ContractDataCache { /// All contract definitions in this compilation unit, in registration /// order (deterministic iteration for `all_contracts`). contracts: Vec, - /// Lookup by simple name. Picks one definition arbitrarily if multiple - /// contracts share the same name across files. - contract_by_name: HashMap, /// Per-contract derived data, keyed by contract `NodeId`. data: HashMap, } @@ -34,7 +31,6 @@ pub(super) struct ContractDataCache { impl ContractDataCache { pub(super) fn build_from(binder: &Binder, types: &TypeRegistry) -> Self { let mut contracts = Vec::new(); - let mut contract_by_name = HashMap::new(); let mut data = HashMap::new(); for (contract_id, definition) in binder.definitions() { @@ -43,7 +39,6 @@ impl ContractDataCache { }; let contract_id = *contract_id; let ir_node = Arc::clone(&contract.ir_node); - let name = contract.ir_node.name.unparse().to_string(); let linearised_functions = compute_linearised_functions(binder, types, contract_id); let linearised_state_variables = @@ -61,15 +56,10 @@ impl ContractDataCache { }, ); - contract_by_name.insert(name, Arc::clone(&ir_node)); contracts.push(ir_node); } - Self { - contracts, - contract_by_name, - data, - } + Self { contracts, data } } fn get(&self, contract_id: NodeId) -> &ContractData { @@ -82,8 +72,14 @@ impl ContractDataCache { self.contracts.iter() } - pub(super) fn find_contract_by_name(&self, name: &str) -> Option<&ir::ContractDefinition> { - self.contract_by_name.get(name) + pub(super) fn find_contract_by_name<'a>( + &'a self, + name: &'a str, + ) -> impl Iterator + use<'a> { + self.contracts + .iter() + .filter(move |contract| contract.name.unparse() == name) + .cloned() } pub(super) fn linearised_functions(&self, contract_id: NodeId) -> &[ir::FunctionDefinition] { diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs b/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs index bdcd45bcc6..46592de125 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs @@ -107,14 +107,19 @@ impl SemanticContext { self.binder.references().values() } - /// Iterates over every contract definition in this compilation unit, in - /// registration order. + /// Iterates over every contract definition in this compilation unit. pub fn all_contracts(&self) -> impl Iterator + use<'_> { self.contract_data.all_contracts() } - pub fn find_contract_by_name(&self, name: &str) -> Option { - self.contract_data.find_contract_by_name(name).cloned() + pub fn find_contract_by_name<'a, 'b>( + &'a self, + name: &'b str, + ) -> impl Iterator + use<'a> + where + 'b: 'a, + { + self.contract_data.find_contract_by_name(name) } } diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/compilation/unit.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/compilation/unit.rs index 33afa5ad24..c25802d74f 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/compilation/unit.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/compilation/unit.rs @@ -74,14 +74,19 @@ impl CompilationUnit { }) } - pub fn find_contract_by_name(&self, name: &str) -> Option { + pub fn find_contract_by_name<'a, 'b>( + &'a self, + name: &'b str, + ) -> impl Iterator + use<'a> + where + 'b: 'a, + { self.semantic .find_contract_by_name(name) .map(|contract| ast::create_contract_definition(&contract, &self.semantic)) } - /// Iterates over every contract definition in this compilation unit, in - /// registration order. + /// Iterates over every contract definition in this compilation unit. pub fn all_contracts(&self) -> impl Iterator + use<'_> { self.semantic .all_contracts() diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/internal_signature.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/internal_signature.rs index 98b9898869..da25837861 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/internal_signature.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/internal_signature.rs @@ -4,6 +4,7 @@ fn test_compute_internal_signature() { let test_contract = unit .find_contract_by_name("Test") + .next() .expect("Test contract can be found"); // Functions are linearised in alphabetical order, with the unnamed diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/selectors.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/selectors.rs index d64cf6dc75..0cba5d7877 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/selectors.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/selectors.rs @@ -6,6 +6,7 @@ fn test_function_selector() { let counter = unit .find_contract_by_name("Counter") + .next() .expect("contract can be found"); let functions = counter.linearised_functions(); @@ -34,6 +35,7 @@ fn test_events_and_errors_selectors() { let test_contract = unit .find_contract_by_name("Test") + .next() .expect("Test contract can be found"); let events = test_contract.events(); @@ -51,6 +53,7 @@ fn test_selectors_for_functions_with_tuple_parameters() { let test = unit .find_contract_by_name("Test") + .next() .expect("contract is found"); let functions = test.functions(); diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/storage_layout.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/storage_layout.rs index 6c1504b1f8..f2955dfb1c 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/storage_layout.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/storage_layout.rs @@ -73,6 +73,7 @@ fn test_storage_layout() { let counter = unit .find_contract_by_name("C") + .next() .expect("contract can be found"); let counter_abi = counter.compute_abi().expect("can compute ABI"); let layout = counter_abi.storage_layout(); @@ -102,6 +103,7 @@ fn test_transient_and_custom_storage_layout() { let d_contract = unit .find_contract_by_name("D") + .next() .expect("contract can be found"); let d_abi = d_contract.compute_abi().expect("can compute ABI"); let d_layout = d_abi.storage_layout(); @@ -112,6 +114,7 @@ fn test_transient_and_custom_storage_layout() { let e_contract = unit .find_contract_by_name("E") + .next() .expect("contract can be found"); let e_abi = e_contract.compute_abi().expect("can compute ABI"); let e_layout = e_abi.storage_layout(); @@ -132,6 +135,7 @@ fn test_erc7201_storage_layout() { let f_contract = unit .find_contract_by_name("F") + .next() .expect("contract can be found"); let f_abi = f_contract.compute_abi().expect("can compute ABI"); let f_layout = f_abi.storage_layout(); diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/definition_references.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/definition_references.rs index 54fb14c93d..4d4c758be1 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/definition_references.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/definition_references.rs @@ -7,6 +7,7 @@ fn test_definition_references() { let ownable = unit .find_contract_by_name("Ownable") + .next() .expect("can find Ownable contract"); // find the `onlyOwner` modifier defined in the `Ownable` contract diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/identifier_path_resolution.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/identifier_path_resolution.rs index 50b79724ea..b8c8fe0a7c 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/identifier_path_resolution.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/identifier_path_resolution.rs @@ -28,6 +28,7 @@ fn test_identifier_path_resolve_to_immediate_definition() { let counter = unit .find_contract_by_name("Counter") + .next() .expect("contract is found"); let counter_bases: Vec<_> = counter .inheritance_types() @@ -61,7 +62,10 @@ fn test_identifier_path_resolve_to_immediate_definition() { fn test_identifier_path_resolve_to_immediate_resolves_to_direct_definition() { let unit = ChainedImports::build_compilation_unit(); - let a1 = unit.find_contract_by_name("A1").expect("contract is found"); + let a1 = unit + .find_contract_by_name("A1") + .next() + .expect("contract is found"); let i1_typename = a1 .inheritance_types() .iter() @@ -86,7 +90,10 @@ fn test_identifier_path_resolve_to_immediate_resolves_to_direct_definition() { fn test_chained_imports_resolution() { let unit = ChainedImports::build_compilation_unit(); - let a1 = unit.find_contract_by_name("A1").expect("contract is found"); + let a1 = unit + .find_contract_by_name("A1") + .next() + .expect("contract is found"); let b1_typename = a1 .inheritance_types() .iter() diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/linearisations.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/linearisations.rs index 2e9000be49..64f8dbfe73 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/linearisations.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/linearisations.rs @@ -32,6 +32,7 @@ fn test_contract_compute_linearised_bases() { let counter = unit .find_contract_by_name("Counter") + .next() .expect("can find Counter contract"); let bases = counter.linearised_bases(); assert_eq!(bases.len(), 3); @@ -56,6 +57,7 @@ fn test_contract_compute_linearised_state_variables() { let counter = unit .find_contract_by_name("Counter") + .next() .expect("can find Counter contract"); let state_variables = counter.linearised_state_variables(); @@ -73,6 +75,7 @@ fn test_contract_compute_linearised_functions() { let counter = unit .find_contract_by_name("Counter") + .next() .expect("can find Counter contract"); let functions = counter.linearised_functions(); @@ -101,6 +104,7 @@ fn test_contract_compute_linearised_functions_with_overrides() { let inherited = unit .find_contract_by_name("Inherited") + .next() .expect("can find contract"); let functions = inherited.linearised_functions(); assert_eq!(functions.len(), 3); diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/members.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/members.rs index cd6459c228..fcf14170b7 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/members.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/members.rs @@ -7,6 +7,7 @@ fn test_contract_direct_bases() { let counter = unit .find_contract_by_name("Counter") + .next() .expect("can find Counter contract"); let bases = counter.direct_bases(); assert_eq!(bases.len(), 2); @@ -27,6 +28,7 @@ fn test_contract_constructor_and_modifiers() { let counter = unit .find_contract_by_name("Counter") + .next() .expect("can find Counter contract"); let constructor = counter.constructor(); diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/node_location.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/node_location.rs index e44dd80078..77cea9f371 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/node_location.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/node_location.rs @@ -7,6 +7,7 @@ fn test_get_file_id_and_text_range() { let ownable = unit .find_contract_by_name("Ownable") + .next() .expect("contract is found"); assert_eq!(ownable.get_file_id(), "ownable.sol"); @@ -30,11 +31,13 @@ fn test_get_file_id_and_text_range() { let activatable = unit .find_contract_by_name("Activatable") + .next() .expect("contract is found"); assert_eq!(activatable.get_file_id(), "activatable.sol"); let counter = unit .find_contract_by_name("Counter") + .next() .expect("contract is found"); assert_eq!(counter.get_file_id(), "main.sol"); } diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/typing.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/typing.rs index fcb5d46943..d37227ea0f 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/typing.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/ast/typing.rs @@ -7,6 +7,7 @@ fn test_get_type() { let ownable = unit .find_contract_by_name("Ownable") + .next() .expect("contract is found"); let state_variables = ownable @@ -37,6 +38,7 @@ fn test_function_get_type() { let counter = unit .find_contract_by_name("Counter") + .next() .expect("contract is found"); let increment = counter diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/unit.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/unit.rs index 185ba4affe..f63ac072c7 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/unit.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/unit.rs @@ -71,12 +71,15 @@ fn test_find_contract_by_name() { let counter = unit .find_contract_by_name("Counter") + .next() .expect("Counter contract is found"); let ownable = unit .find_contract_by_name("Ownable") + .next() .expect("Ownable contract is found"); let activatable = unit .find_contract_by_name("Activatable") + .next() .expect("Activatable contract is found"); assert_eq!(counter.name().name(), "Counter"); From 6e4d1568198ab3a48a6cdaf8e8ed2010c9774a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Fri, 5 Jun 2026 17:55:08 -0400 Subject: [PATCH 3/5] Update public-api.txt snapshots --- .../solidity-v2/outputs/cargo/semantic/generated/public_api.txt | 2 +- .../outputs/cargo/slang_solidity/generated/public_api.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/solidity-v2/outputs/cargo/semantic/generated/public_api.txt b/crates/solidity-v2/outputs/cargo/semantic/generated/public_api.txt index 12bf9bff4e..c3a0b02298 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/generated/public_api.txt +++ b/crates/solidity-v2/outputs/cargo/semantic/generated/public_api.txt @@ -278,7 +278,7 @@ pub fn slang_solidity_v2_semantic::context::SemanticContext::all_definitions(&se pub fn slang_solidity_v2_semantic::context::SemanticContext::all_references(&self) -> impl core::iter::traits::iterator::Iterator + use<'_> pub fn slang_solidity_v2_semantic::context::SemanticContext::binder(&self) -> &slang_solidity_v2_semantic::binder::Binder pub fn slang_solidity_v2_semantic::context::SemanticContext::build_from(language_version: slang_solidity_v2_common::versions::version::LanguageVersion, files: &[impl slang_solidity_v2_semantic::context::SemanticFile], diagnostics: &mut slang_solidity_v2_common::diagnostics::collection::DiagnosticCollection) -> Self -pub fn slang_solidity_v2_semantic::context::SemanticContext::find_contract_by_name(&self, name: &str) -> core::option::Option +pub fn slang_solidity_v2_semantic::context::SemanticContext::find_contract_by_name<'a, 'b>(&'a self, name: &'b str) -> impl core::iter::traits::iterator::Iterator + use<'a> where 'b: 'a pub fn slang_solidity_v2_semantic::context::SemanticContext::types(&self) -> &slang_solidity_v2_semantic::types::TypeRegistry pub trait slang_solidity_v2_semantic::context::SemanticFile pub fn slang_solidity_v2_semantic::context::SemanticFile::id(&self) -> &str diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/generated/public_api.txt b/crates/solidity-v2/outputs/cargo/slang_solidity/generated/public_api.txt index a34e8d1032..68a6d11f20 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/generated/public_api.txt +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/generated/public_api.txt @@ -28,7 +28,7 @@ pub fn slang_solidity_v2::compilation::CompilationUnit::diagnostics(&self) -> &s pub fn slang_solidity_v2::compilation::CompilationUnit::file(&self, id: &str) -> core::option::Option pub fn slang_solidity_v2::compilation::CompilationUnit::file_ids(&self) -> alloc::vec::Vec pub fn slang_solidity_v2::compilation::CompilationUnit::files(&self) -> impl core::iter::traits::iterator::Iterator + use<'_> -pub fn slang_solidity_v2::compilation::CompilationUnit::find_contract_by_name(&self, name: &str) -> core::option::Option +pub fn slang_solidity_v2::compilation::CompilationUnit::find_contract_by_name<'a, 'b>(&'a self, name: &'b str) -> impl core::iter::traits::iterator::Iterator + use<'a> where 'b: 'a pub fn slang_solidity_v2::compilation::CompilationUnit::language_version(&self) -> slang_solidity_v2_common::versions::version::LanguageVersion pub struct slang_solidity_v2::compilation::FileStruct impl slang_solidity_v2::compilation::FileStruct From 4a416213d192837d20d1d37009faf2c10d5f1893 Mon Sep 17 00:00:00 2001 From: Gustavo Giraldez Date: Mon, 8 Jun 2026 17:39:07 -0400 Subject: [PATCH 4/5] Build `ContractData` in a new semantic pass Add validation TODO comments there, to be implemented later. Rename data structures to better reflect their new role. --- .../semantic/src/context/contract_data.rs | 74 ++++++++++ .../outputs/cargo/semantic/src/context/mod.rs | 9 +- .../outputs/cargo/semantic/src/passes/mod.rs | 1 + .../p5_compute_linearisations/mod.rs} | 130 ++++++------------ 4 files changed, 125 insertions(+), 89 deletions(-) create mode 100644 crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data.rs rename crates/solidity-v2/outputs/cargo/semantic/src/{context/contract_data_cache.rs => passes/p5_compute_linearisations/mod.rs} (61%) diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data.rs b/crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data.rs new file mode 100644 index 0000000000..d6c988eb2f --- /dev/null +++ b/crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data.rs @@ -0,0 +1,74 @@ +use std::collections::HashMap; + +use slang_solidity_v2_common::nodes::NodeId; +use slang_solidity_v2_ir::ir; + +/// Pre-computed member linearisations for a single contract. +#[allow(clippy::struct_field_names)] +pub(crate) struct ContractLinearisations { + pub(crate) functions: Vec, + pub(crate) state_variables: Vec, + pub(crate) errors: Vec, + pub(crate) events: Vec, +} + +/// Cache of derived data about contracts stored on the `SemanticContext`. Every +/// contract's `NodeId` has an entry in `data`. +pub(crate) struct ContractData { + /// All contract definitions in this compilation unit, in registration + /// order (deterministic iteration for `all_contracts`). + contracts: Vec, + /// Per-contract linearised members, keyed by contract `NodeId`. + linearisations: HashMap, +} + +impl ContractData { + pub(crate) fn new( + contracts: Vec, + data: HashMap, + ) -> Self { + Self { + contracts, + linearisations: data, + } + } + + fn get(&self, contract_id: NodeId) -> &ContractLinearisations { + self.linearisations + .get(&contract_id) + .expect("contract_id is a registered contract") + } + + pub(super) fn all_contracts(&self) -> impl Iterator { + self.contracts.iter() + } + + pub(super) fn find_contract_by_name<'a>( + &'a self, + name: &'a str, + ) -> impl Iterator + use<'a> { + self.contracts + .iter() + .filter(move |contract| contract.name.unparse() == name) + .cloned() + } + + pub(super) fn linearised_functions(&self, contract_id: NodeId) -> &[ir::FunctionDefinition] { + &self.get(contract_id).functions + } + + pub(super) fn linearised_state_variables( + &self, + contract_id: NodeId, + ) -> &[ir::StateVariableDefinition] { + &self.get(contract_id).state_variables + } + + pub(super) fn linearised_errors(&self, contract_id: NodeId) -> &[ir::ErrorDefinition] { + &self.get(contract_id).errors + } + + pub(super) fn linearised_events(&self, contract_id: NodeId) -> &[ir::EventDefinition] { + &self.get(contract_id).events + } +} diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs b/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs index 46592de125..425f4a3ad8 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use contract_data_cache::ContractDataCache; +pub(crate) use contract_data::{ContractData, ContractLinearisations}; use file_node_mapper::FileNodeMapper; use slang_solidity_v2_common::diagnostics::DiagnosticCollection; use slang_solidity_v2_common::nodes::NodeId; @@ -11,6 +11,7 @@ use slang_solidity_v2_ir::ir; use crate::binder::{Binder, Definition, Reference}; use crate::passes::{ p1_collect_definitions, p2_linearise_contracts, p3_type_definitions, p4_resolve_references, + p5_compute_linearisations, }; use crate::types::{ ArrayType, ByteArrayType, ContractType, EnumType, FixedPointNumberType, FixedSizeArrayType, @@ -18,7 +19,7 @@ use crate::types::{ TypeRegistry, UserDefinedValueType, }; -mod contract_data_cache; +mod contract_data; mod file_node_mapper; /// Trait for files that can be used as input to the semantic analysis passes. @@ -61,7 +62,7 @@ pub struct SemanticContext { binder: Binder, types: TypeRegistry, file_node_mapper: FileNodeMapper, - contract_data: ContractDataCache, + contract_data: ContractData, } impl SemanticContext { @@ -77,9 +78,9 @@ impl SemanticContext { p2_linearise_contracts::run(files, &mut binder, diagnostics); p3_type_definitions::run(files, &mut binder, &mut types, language_version); p4_resolve_references::run(files, &mut binder, &mut types, language_version); + let contract_data = p5_compute_linearisations::run(&binder, &types); let file_node_mapper = FileNodeMapper::build_from(files); - let contract_data = ContractDataCache::build_from(&binder, &types); Self { binder, diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/passes/mod.rs b/crates/solidity-v2/outputs/cargo/semantic/src/passes/mod.rs index 59177c3130..5eda86c4d7 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/passes/mod.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/passes/mod.rs @@ -3,6 +3,7 @@ pub(crate) mod p1_collect_definitions; pub(crate) mod p2_linearise_contracts; pub(crate) mod p3_type_definitions; pub(crate) mod p4_resolve_references; +pub(crate) mod p5_compute_linearisations; #[cfg(test)] mod tests; diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data_cache.rs b/crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_compute_linearisations/mod.rs similarity index 61% rename from crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data_cache.rs rename to crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_compute_linearisations/mod.rs index b2652456f2..2655e01892 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/context/contract_data_cache.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_compute_linearisations/mod.rs @@ -6,99 +6,49 @@ use slang_solidity_v2_common::nodes::NodeId; use slang_solidity_v2_ir::ir; use crate::binder::{Binder, Definition}; +use crate::context::{ContractData, ContractLinearisations}; use crate::types::TypeRegistry; -/// Pre-computed derived data for a single contract. -#[allow(clippy::struct_field_names)] -struct ContractData { - linearised_functions: Vec, - linearised_state_variables: Vec, - linearised_errors: Vec, - linearised_events: Vec, -} - -/// Cache of derived data about contracts, computed once at the end of the -/// semantic passes and stored on the `SemanticContext`. Every contract's -/// `NodeId` has an entry in `data`. -pub(super) struct ContractDataCache { - /// All contract definitions in this compilation unit, in registration - /// order (deterministic iteration for `all_contracts`). - contracts: Vec, - /// Per-contract derived data, keyed by contract `NodeId`. - data: HashMap, -} - -impl ContractDataCache { - pub(super) fn build_from(binder: &Binder, types: &TypeRegistry) -> Self { - let mut contracts = Vec::new(); - let mut data = HashMap::new(); - - for (contract_id, definition) in binder.definitions() { - let Definition::Contract(contract) = definition else { - continue; - }; - let contract_id = *contract_id; - let ir_node = Arc::clone(&contract.ir_node); - - let linearised_functions = compute_linearised_functions(binder, types, contract_id); - let linearised_state_variables = - collect_linearised_state_variables(binder, contract_id); - let linearised_errors = collect_linearised_errors(binder, contract_id); - let linearised_events = collect_linearised_events(binder, contract_id); - - data.insert( - contract_id, - ContractData { - linearised_functions, - linearised_state_variables, - linearised_errors, - linearised_events, - }, - ); - - contracts.push(ir_node); - } - - Self { contracts, data } - } - - fn get(&self, contract_id: NodeId) -> &ContractData { - self.data - .get(&contract_id) - .expect("contract_id is a registered contract") - } +/// In this pass we walk every contract's linearised bases and pre-compute the +/// collections of functions, state variables, errors and events visible in the +/// contract's hierarchy, storing them in a `ContractDataCache`. +pub fn run(binder: &Binder, types: &TypeRegistry) -> ContractData { + let mut contracts = Vec::new(); + let mut data = HashMap::new(); - pub(super) fn all_contracts(&self) -> impl Iterator { - self.contracts.iter() - } - - pub(super) fn find_contract_by_name<'a>( - &'a self, - name: &'a str, - ) -> impl Iterator + use<'a> { - self.contracts - .iter() - .filter(move |contract| contract.name.unparse() == name) - .cloned() - } + for (contract_id, definition) in binder.definitions() { + let Definition::Contract(contract) = definition else { + continue; + }; + let contract_id = *contract_id; - pub(super) fn linearised_functions(&self, contract_id: NodeId) -> &[ir::FunctionDefinition] { - &self.get(contract_id).linearised_functions - } + let ir_node = Arc::clone(&contract.ir_node); + contracts.push(ir_node); - pub(super) fn linearised_state_variables( - &self, - contract_id: NodeId, - ) -> &[ir::StateVariableDefinition] { - &self.get(contract_id).linearised_state_variables + let linearisations = compute_linearised_members(binder, types, contract_id); + data.insert(contract_id, linearisations); } - pub(super) fn linearised_errors(&self, contract_id: NodeId) -> &[ir::ErrorDefinition] { - &self.get(contract_id).linearised_errors - } + ContractData::new(contracts, data) +} - pub(super) fn linearised_events(&self, contract_id: NodeId) -> &[ir::EventDefinition] { - &self.get(contract_id).linearised_events +fn compute_linearised_members( + binder: &Binder, + types: &TypeRegistry, + contract_id: NodeId, +) -> ContractLinearisations { + let functions = compute_linearised_functions(binder, types, contract_id); + let state_variables = collect_linearised_state_variables(binder, contract_id); + let errors = collect_linearised_errors(binder, contract_id); + let events = collect_linearised_events(binder, contract_id); + + // TODO(validation): check that there is no redefinition of identifiers among all contracts in the hierarchy + + ContractLinearisations { + functions, + state_variables, + errors, + events, } } @@ -136,6 +86,8 @@ fn compute_linearised_functions( if !overridden { functions.push(Arc::clone(function)); } + // TODO(validation): if overriding, function must have the `override` specifier and the overriden functions must be marked `virtual` + // TODO(validation): if overriding multiple ancestors, the function needs to specify the bases in a specifier } } @@ -170,6 +122,7 @@ fn function_overrides( } _ => false, } + // TODO(validation) SDR[6]: check also that the function mutability is stricter than other's } /// Walks the linearised bases in reverse (most-base first) and concatenates @@ -191,6 +144,10 @@ fn collect_linearised_state_variables( if let ir::ContractMember::StateVariableDefinition(state_variable) = member { state_variables.push(Arc::clone(state_variable)); } + // TODO(validation): check for duplicate declarations + // TODO(validation): if the state variable is `public`, check if it + // overrides a function and validate the presence of `override` (in + // the variable) and `virtual` (in the function) modifiers } } state_variables @@ -213,6 +170,7 @@ fn collect_linearised_errors(binder: &Binder, contract_id: NodeId) -> Vec Vec Date: Tue, 9 Jun 2026 15:38:09 -0400 Subject: [PATCH 5/5] Reorder semantic passes Compute linearisations before resolving references --- .../solidity-v2/outputs/cargo/semantic/src/context/mod.rs | 8 ++++---- .../solidity-v2/outputs/cargo/semantic/src/passes/mod.rs | 4 ++-- .../mod.rs | 4 ++-- .../disambiguation.rs | 0 .../mod.rs | 0 .../resolution.rs | 0 .../typing.rs | 0 .../visitor.rs | 0 .../outputs/cargo/semantic/src/passes/tests/binder.rs | 4 ++-- .../outputs/cargo/semantic/src/passes/tests/typing.rs | 4 ++-- 10 files changed, 12 insertions(+), 12 deletions(-) rename crates/solidity-v2/outputs/cargo/semantic/src/passes/{p5_compute_linearisations => p4_compute_linearisations}/mod.rs (98%) rename crates/solidity-v2/outputs/cargo/semantic/src/passes/{p4_resolve_references => p5_resolve_references}/disambiguation.rs (100%) rename crates/solidity-v2/outputs/cargo/semantic/src/passes/{p4_resolve_references => p5_resolve_references}/mod.rs (100%) rename crates/solidity-v2/outputs/cargo/semantic/src/passes/{p4_resolve_references => p5_resolve_references}/resolution.rs (100%) rename crates/solidity-v2/outputs/cargo/semantic/src/passes/{p4_resolve_references => p5_resolve_references}/typing.rs (100%) rename crates/solidity-v2/outputs/cargo/semantic/src/passes/{p4_resolve_references => p5_resolve_references}/visitor.rs (100%) diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs b/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs index 425f4a3ad8..4c06ce3514 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/context/mod.rs @@ -10,8 +10,8 @@ use slang_solidity_v2_ir::ir; use crate::binder::{Binder, Definition, Reference}; use crate::passes::{ - p1_collect_definitions, p2_linearise_contracts, p3_type_definitions, p4_resolve_references, - p5_compute_linearisations, + p1_collect_definitions, p2_linearise_contracts, p3_type_definitions, p4_compute_linearisations, + p5_resolve_references, }; use crate::types::{ ArrayType, ByteArrayType, ContractType, EnumType, FixedPointNumberType, FixedSizeArrayType, @@ -77,8 +77,8 @@ impl SemanticContext { p1_collect_definitions::run(files, &mut binder, diagnostics); p2_linearise_contracts::run(files, &mut binder, diagnostics); p3_type_definitions::run(files, &mut binder, &mut types, language_version); - p4_resolve_references::run(files, &mut binder, &mut types, language_version); - let contract_data = p5_compute_linearisations::run(&binder, &types); + let contract_data = p4_compute_linearisations::run(&binder, &types); + p5_resolve_references::run(files, &mut binder, &mut types, language_version); let file_node_mapper = FileNodeMapper::build_from(files); diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/passes/mod.rs b/crates/solidity-v2/outputs/cargo/semantic/src/passes/mod.rs index 5eda86c4d7..460a41aa40 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/passes/mod.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/passes/mod.rs @@ -2,8 +2,8 @@ mod common; pub(crate) mod p1_collect_definitions; pub(crate) mod p2_linearise_contracts; pub(crate) mod p3_type_definitions; -pub(crate) mod p4_resolve_references; -pub(crate) mod p5_compute_linearisations; +pub(crate) mod p4_compute_linearisations; +pub(crate) mod p5_resolve_references; #[cfg(test)] mod tests; diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_compute_linearisations/mod.rs b/crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_compute_linearisations/mod.rs similarity index 98% rename from crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_compute_linearisations/mod.rs rename to crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_compute_linearisations/mod.rs index 2655e01892..e95b1867e5 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_compute_linearisations/mod.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_compute_linearisations/mod.rs @@ -37,7 +37,7 @@ fn compute_linearised_members( types: &TypeRegistry, contract_id: NodeId, ) -> ContractLinearisations { - let functions = compute_linearised_functions(binder, types, contract_id); + let functions = collect_linearised_functions(binder, types, contract_id); let state_variables = collect_linearised_state_variables(binder, contract_id); let errors = collect_linearised_errors(binder, contract_id); let events = collect_linearised_events(binder, contract_id); @@ -52,7 +52,7 @@ fn compute_linearised_members( } } -fn compute_linearised_functions( +fn collect_linearised_functions( binder: &Binder, types: &TypeRegistry, contract_id: NodeId, diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_resolve_references/disambiguation.rs b/crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_resolve_references/disambiguation.rs similarity index 100% rename from crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_resolve_references/disambiguation.rs rename to crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_resolve_references/disambiguation.rs diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_resolve_references/mod.rs b/crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_resolve_references/mod.rs similarity index 100% rename from crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_resolve_references/mod.rs rename to crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_resolve_references/mod.rs diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_resolve_references/resolution.rs b/crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_resolve_references/resolution.rs similarity index 100% rename from crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_resolve_references/resolution.rs rename to crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_resolve_references/resolution.rs diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_resolve_references/typing.rs b/crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_resolve_references/typing.rs similarity index 100% rename from crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_resolve_references/typing.rs rename to crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_resolve_references/typing.rs diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_resolve_references/visitor.rs b/crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_resolve_references/visitor.rs similarity index 100% rename from crates/solidity-v2/outputs/cargo/semantic/src/passes/p4_resolve_references/visitor.rs rename to crates/solidity-v2/outputs/cargo/semantic/src/passes/p5_resolve_references/visitor.rs diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/passes/tests/binder.rs b/crates/solidity-v2/outputs/cargo/semantic/src/passes/tests/binder.rs index 2c7f0c3d2c..322a9eabee 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/passes/tests/binder.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/passes/tests/binder.rs @@ -9,7 +9,7 @@ use slang_solidity_v2_ir::ir::NodeIdGenerator; use super::build_file; use crate::binder::{Binder, Resolution}; use crate::passes::{ - p1_collect_definitions, p2_linearise_contracts, p3_type_definitions, p4_resolve_references, + p1_collect_definitions, p2_linearise_contracts, p3_type_definitions, p5_resolve_references, }; use crate::types::TypeRegistry; @@ -278,7 +278,7 @@ contract Test is Base { "Semantic diagnostics: {diagnostics:?}" ); p3_type_definitions::run(&files, &mut binder, &mut types, language_version); - p4_resolve_references::run(&files, &mut binder, &mut types, language_version); + p5_resolve_references::run(&files, &mut binder, &mut types, language_version); // Verify that references were created and most are resolved let references = binder.references(); diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/passes/tests/typing.rs b/crates/solidity-v2/outputs/cargo/semantic/src/passes/tests/typing.rs index 563b9b9d0a..d602a1baee 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/passes/tests/typing.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/passes/tests/typing.rs @@ -9,7 +9,7 @@ use crate::binder::Binder; use crate::context::SemanticFile; use crate::passes::common::node_id_for_expression_typing; use crate::passes::{ - p1_collect_definitions, p2_linearise_contracts, p3_type_definitions, p4_resolve_references, + p1_collect_definitions, p2_linearise_contracts, p3_type_definitions, p5_resolve_references, }; use crate::types::{ ByteArrayType, BytesType, ContractType, DataLocation, FixedSizeArrayType, IntegerType, @@ -38,7 +38,7 @@ fn analyze(language_version: LanguageVersion, source: &str) -> TypeAnalysis { "Semantic diagnostics: {diagnostics:?}" ); p3_type_definitions::run(&files, &mut binder, &mut types, language_version); - p4_resolve_references::run(&files, &mut binder, &mut types, language_version); + p5_resolve_references::run(&files, &mut binder, &mut types, language_version); TypeAnalysis { file: files.into_iter().next().unwrap(),