From 9d03c414dfd2d7060be0b59aad0e0a02d4b1d8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Mon, 19 Jan 2026 13:38:46 -0500 Subject: [PATCH 1/8] Retain references to `ImportDeconstructionSymbol`s instead of following If an identifier resolves lexically to an `ImportDeconstructionSymbol` definition, register that instead of skipping it and registering to the actual aliased definition. This allows keeping better track of referenced imports. The conterpart is that we need to explicitly follow through the aliases whenever we need access to the actual definition, eg. when resolving types, members, etc. --- .../cargo/crate/src/backend/binder/mod.rs | 61 +++++++++---------- .../ir/ast/node_extensions/identifiers.rs | 27 +++++--- .../passes/p3_linearise_contracts/mod.rs | 13 +++- .../passes/p4_type_definitions/resolution.rs | 21 ++++++- .../passes/p4_type_definitions/typing.rs | 9 ++- .../passes/p4_type_definitions/visitor.rs | 23 ++++--- .../p5_resolve_references/resolution.rs | 5 +- .../passes/p5_resolve_references/typing.rs | 8 ++- .../passes/p5_resolve_references/visitor.rs | 8 ++- .../v2/generated/0.4.11-success.txt | 8 +-- .../imported/v2/generated/0.4.11-success.txt | 8 +-- .../global/v2/generated/0.4.11-failure.txt | 4 +- .../global/v2/generated/0.6.0-failure.txt | 4 +- .../global/v2/generated/0.7.1-failure.txt | 4 +- .../global/v2/generated/0.7.4-failure.txt | 4 +- .../global/v2/generated/0.8.0-failure.txt | 4 +- .../global/v2/generated/0.8.13-success.txt | 4 +- .../global/v2/generated/0.8.4-failure.txt | 4 +- .../global/v2/generated/0.8.8-failure.txt | 4 +- .../v2/generated/0.8.13-success.txt | 8 +-- .../v2/generated/0.4.11-failure.txt | 4 +- .../v2/generated/0.6.0-failure.txt | 4 +- .../v2/generated/0.7.1-failure.txt | 4 +- .../v2/generated/0.7.4-success.txt | 4 +- .../v2/generated/0.4.11-failure.txt | 8 +-- 25 files changed, 155 insertions(+), 100 deletions(-) diff --git a/crates/solidity/outputs/cargo/crate/src/backend/binder/mod.rs b/crates/solidity/outputs/cargo/crate/src/backend/binder/mod.rs index 985d836747..39652a4975 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/binder/mod.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/binder/mod.rs @@ -481,11 +481,14 @@ impl Binder { } } - fn resolve_in_scope_internal(&self, scope_id: ScopeId, symbol: &str) -> Resolution { + // This function attempts to lexically resolve `symbol` starting from the + // given scope. Certain scopes can delegate to their "parent" scopes if + // the symbol is not found there. + pub(crate) fn resolve_in_scope(&self, scope_id: ScopeId, symbol: &str) -> Resolution { let scope = self.get_scope_by_id(scope_id); match scope { Scope::Block(block_scope) => block_scope.definitions.get(symbol).copied().map_or_else( - || self.resolve_in_scope_internal(block_scope.parent_scope_id, symbol), + || self.resolve_in_scope(block_scope.parent_scope_id, symbol), Resolution::Definition, ), Scope::Contract(contract_scope) => { @@ -496,7 +499,7 @@ impl Binder { ) .or_else(|| { // Otherwise, delegate to the containing file scope. - self.resolve_in_scope_internal(contract_scope.file_scope_id, symbol) + self.resolve_in_scope(contract_scope.file_scope_id, symbol) }) } Scope::Enum(enum_scope) => enum_scope.definitions.get(symbol).into(), @@ -506,16 +509,16 @@ impl Binder { .get(symbol) .copied() .map_or_else( - || self.resolve_in_scope_internal(function_scope.parameters_scope_id, symbol), + || self.resolve_in_scope(function_scope.parameters_scope_id, symbol), Resolution::Definition, ) - .or_else(|| self.resolve_in_scope_internal(function_scope.parent_scope_id, symbol)), + .or_else(|| self.resolve_in_scope(function_scope.parent_scope_id, symbol)), Scope::Modifier(modifier_scope) => { if symbol == "_" { Resolution::BuiltIn(BuiltIn::ModifierUnderscore) } else { modifier_scope.definitions.get(symbol).copied().map_or_else( - || self.resolve_in_scope_internal(modifier_scope.parent_scope_id, symbol), + || self.resolve_in_scope(modifier_scope.parent_scope_id, symbol), Resolution::Definition, ) } @@ -534,7 +537,7 @@ impl Binder { .get(symbol) .copied() .map_or_else( - || self.resolve_in_scope_internal(yul_block_scope.parent_scope_id, symbol), + || self.resolve_in_scope(yul_block_scope.parent_scope_id, symbol), Resolution::Definition, ), Scope::YulFunction(yul_function_scope) => { @@ -545,40 +548,33 @@ impl Binder { .get(symbol) .copied() .map_or_else( - || { - self.resolve_in_scope_internal( - yul_function_scope.parent_scope_id, - symbol, - ) - }, + || self.resolve_in_scope(yul_function_scope.parent_scope_id, symbol), Resolution::Definition, ) } } } - // This will attempt to lexically resolve `symbol` starting from the given - // scope. This means that scopes can delegate to their "parent" scopes if - // the symbol is not found there, and also that imported symbols are - // followed recursively. This function handles the latter (following - // imported symbols recursively), while `resolve_in_scope_internal` - // delegates to parent or otherwise linked scopes. - pub(crate) fn resolve_in_scope(&self, scope_id: ScopeId, symbol: &str) -> Resolution { + // If the resolution points to definitions that are symbols aliases (eg. + // import deconstruction symbols) this function will recursively follow them + // and return an appropriate resulting resolution. Ambiguities and missing + // definitions can occur along the followed aliases, so there is no + // guarantee that a `Resolved` resolution will yield another `Resolved` + // resolution. + pub(crate) fn follow_symbol_aliases(&self, resolution: &Resolution) -> Resolution { + match resolution { + Resolution::Unresolved | Resolution::BuiltIn(_) => return resolution.clone(), + _ => {} + } + // TODO: since this function uses the results from other resolution // functions, we making more allocations than necessary; it may be worth // it to try and avoid them by returning iterators from the delegated // resolution functions let mut found_ids = Vec::new(); - let mut working_set = Vec::new(); let mut seen_ids = HashSet::new(); + let mut working_set = resolution.get_definition_ids(); - let initial_resolution = self.resolve_in_scope_internal(scope_id, symbol); - match initial_resolution { - Resolution::Unresolved | Resolution::BuiltIn(_) => return initial_resolution, - _ => {} - } - - working_set.extend(initial_resolution.get_definition_ids().iter().rev()); while let Some(definition_id) = working_set.pop() { if !seen_ids.insert(definition_id) { // we already processed this definition @@ -597,16 +593,17 @@ impl Binder { continue; }; working_set.extend( - self.resolve_in_scope_internal(scope_id, &imported_symbol.symbol) - .get_definition_ids() - .iter() - .rev(), + self.resolve_in_scope(scope_id, &imported_symbol.symbol) + .get_definition_ids(), ); } else { found_ids.push(definition_id); } } + // reverse the result to maintain the original ordering, since we + // resolved from last to first in the loop above + found_ids.reverse(); Resolution::from(found_ids) } diff --git a/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs b/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs index 796f84393c..c66843ae98 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs @@ -35,13 +35,13 @@ impl IdentifierStruct { .is_some() } - // only makes sense if `is_reference()` is true + // Attempts to resolve the identifier path to a definition, following symbol + // aliases (import deconstructions). This only makes sense if + // `is_reference()` is true. pub fn resolve_to_definition(&self) -> Option { - let reference = self + let definition_id = self .semantic - .binder() - .find_reference_by_identifier_node_id(self.ir_node.id())?; - let definition_id = reference.resolution.as_definition_id()?; + .resolve_reference_identifier_to_definition_id(self.ir_node.id())?; Some(Definition::create(definition_id, &self.semantic)) } @@ -128,6 +128,15 @@ impl SemanticAnalysis { }) .collect() } + + fn resolve_reference_identifier_to_definition_id(&self, node_id: NodeId) -> Option { + let reference = self + .binder() + .find_reference_by_identifier_node_id(node_id)?; + self.binder() + .follow_symbol_aliases(&reference.resolution) + .as_definition_id() + } } impl IdentifierPathStruct { @@ -139,13 +148,13 @@ impl IdentifierPathStruct { .join(".") } + // Attempts to resolve the identifier path to a definition, following symbol + // aliases (import deconstructions) pub fn resolve_to_definition(&self) -> Option { let ir_node = self.ir_nodes.last()?; - let reference = self + let definition_id = self .semantic - .binder() - .find_reference_by_identifier_node_id(ir_node.id())?; - let definition_id = reference.resolution.as_definition_id()?; + .resolve_reference_identifier_to_definition_id(ir_node.id())?; Some(Definition::create(definition_id, &self.semantic)) } } diff --git a/crates/solidity/outputs/cargo/crate/src/backend/passes/p3_linearise_contracts/mod.rs b/crates/solidity/outputs/cargo/crate/src/backend/passes/p3_linearise_contracts/mod.rs index 61b166eddd..c809c51fcc 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/passes/p3_linearise_contracts/mod.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/passes/p3_linearise_contracts/mod.rs @@ -122,14 +122,23 @@ impl<'a> Pass<'a> { } else { Resolution::Unresolved }; - let definition_id = resolution.as_definition_id(); let reference = Reference::new(Rc::clone(identifier), resolution.clone()); self.binder.insert_reference(reference); + // Unless we used namespace resolution and in order to continue + // resolving the identifier path, we should ensure we've followed + // through any symbol alias (ie. import deconstruction symbol) + let resolution = if use_lexical_resolution { + self.binder.follow_symbol_aliases(&resolution) + } else { + resolution + }; + // recurse into file scopes pointed by the resolved definition // to resolve the next identifier in the path - scope_id = definition_id + scope_id = resolution + .as_definition_id() .and_then(|node_id| self.binder.find_definition_by_id(node_id)) .and_then(|definition| match definition { Definition::Import(ImportDefinition { diff --git a/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/resolution.rs b/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/resolution.rs index dca3499e6b..94d48ca321 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/resolution.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/resolution.rs @@ -32,14 +32,23 @@ impl Pass<'_> { } else { Resolution::Unresolved }; - let definition_id = resolution.as_definition_id(); let reference = Reference::new(Rc::clone(identifier), resolution.clone()); self.binder.insert_reference(reference); + // Unless we used namespace resolution and in order to continue + // resolving the identifier path, we should ensure we've followed + // through any symbol alias (ie. import deconstruction symbol) + let resolution = if use_lexical_resolution { + self.binder.follow_symbol_aliases(&resolution) + } else { + resolution + }; + // recurse into file scopes pointed by the resolved definition // to resolve the next identifier in the path - scope_id = definition_id + scope_id = resolution + .as_definition_id() .and_then(|node_id| self.binder.find_definition_by_id(node_id)) .and_then(|definition| match definition { Definition::Import(ImportDefinition { @@ -147,7 +156,13 @@ impl Pass<'_> { self.binder .find_reference_by_identifier_node_id(identifier.id()) }) - .and_then(|reference| reference.resolution.as_definition_id())?; + .and_then(|reference| { + // reference may resolve to an imported library, so we need to + // follow aliases + self.binder + .follow_symbol_aliases(&reference.resolution) + .as_definition_id() + })?; let Some(Definition::Library(_)) = self.binder.find_definition_by_id(definition_id) else { // the referenced definition is not a library diff --git a/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/typing.rs b/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/typing.rs index 30e51d27bf..161bdf3922 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/typing.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/typing.rs @@ -16,7 +16,14 @@ impl Pass<'_> { self.binder .find_reference_by_identifier_node_id(identifier.id()) }) - .and_then(|reference| reference.resolution.as_definition_id()) + .and_then(|reference| { + // We should follow symbol aliases here. This is only relevant + // if the path has a single element, as in other cases symbols + // cannot be aliased. + self.binder + .follow_symbol_aliases(&reference.resolution) + .as_definition_id() + }) .and_then(|node_id| self.type_of_definition(node_id, data_location)) } diff --git a/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/visitor.rs b/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/visitor.rs index bdcc6b00b6..fba42fd049 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/visitor.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/visitor.rs @@ -87,15 +87,22 @@ impl Visitor for Pass<'_> { fn enter_import_deconstruction(&mut self, node: &input_ir::ImportDeconstruction) -> bool { for symbol in &node.symbols { - let target_symbol = if let Some(alias) = &symbol.alias { - alias - } else { - &symbol.name + // find the associated definition to get the imported file ID + let Some(Definition::ImportedSymbol(imported_symbol)) = + self.binder.find_definition_by_id(symbol.node_id) + else { + unreachable!("expected to find definition associated to imported symbol"); }; - let resolution = self.binder.resolve_in_scope( - self.current_contract_or_file_scope_id(), - &target_symbol.unparse(), - ); + // now we can get the target scope ID + let scope_id = imported_symbol + .resolved_file_id + .as_ref() + .and_then(|file_id| self.binder.scope_id_for_file_id(file_id)); + + let resolution = scope_id.map_or(Resolution::Unresolved, |scope_id| { + self.binder + .resolve_in_scope(scope_id, &symbol.name.unparse()) + }); let reference = Reference::new(Rc::clone(&symbol.name), resolution); self.binder.insert_reference(reference); } diff --git a/crates/solidity/outputs/cargo/crate/src/backend/passes/p5_resolve_references/resolution.rs b/crates/solidity/outputs/cargo/crate/src/backend/passes/p5_resolve_references/resolution.rs index 4087e5bdd4..5fc5ff1cca 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/passes/p5_resolve_references/resolution.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/passes/p5_resolve_references/resolution.rs @@ -411,7 +411,10 @@ impl Pass<'_> { resolution }; - scope_id = resolution + // NOTE: we need to follow symbol aliases to resolve the next scope to use + scope_id = self + .binder + .follow_symbol_aliases(&resolution) .as_definition_id() .and_then(|definition_id| self.binder.scope_id_for_node_id(definition_id)); diff --git a/crates/solidity/outputs/cargo/crate/src/backend/passes/p5_resolve_references/typing.rs b/crates/solidity/outputs/cargo/crate/src/backend/passes/p5_resolve_references/typing.rs index 6e06114269..72c18eb836 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/passes/p5_resolve_references/typing.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/passes/p5_resolve_references/typing.rs @@ -139,12 +139,14 @@ impl Pass<'_> { } fn typing_of_identifier(&self, identifier: &Rc) -> Typing { - let resolution = self + let resolution = &self .binder .find_reference_by_identifier_node_id(identifier.id()) .unwrap() - .resolution - .clone(); + .resolution; + // The resolution may point to an imported symbol, so we need to follow + // through in order to get to the actual typing + let resolution = self.binder.follow_symbol_aliases(resolution); self.typing_of_resolution(&resolution) } diff --git a/crates/solidity/outputs/cargo/crate/src/backend/passes/p5_resolve_references/visitor.rs b/crates/solidity/outputs/cargo/crate/src/backend/passes/p5_resolve_references/visitor.rs index 0e86317627..4fe07c4071 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/passes/p5_resolve_references/visitor.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/passes/p5_resolve_references/visitor.rs @@ -635,7 +635,13 @@ impl Visitor for Pass<'_> { let definition_id = self .binder .find_reference_by_identifier_node_id(node.error.last().unwrap().id()) - .and_then(|reference| reference.resolution.as_definition_id()); + .and_then(|reference| { + // Follow symbol aliases as the error type argument to + // revert could be an imported symbol + self.binder + .follow_symbol_aliases(&reference.resolution) + .as_definition_id() + }); self.resolve_named_arguments(named_arguments, definition_id); } } diff --git a/crates/solidity/testing/snapshots/bindings_output/imports/deconstruction/v2/generated/0.4.11-success.txt b/crates/solidity/testing/snapshots/bindings_output/imports/deconstruction/v2/generated/0.4.11-success.txt index 76ca24e0e7..e57647170d 100644 --- a/crates/solidity/testing/snapshots/bindings_output/imports/deconstruction/v2/generated/0.4.11-success.txt +++ b/crates/solidity/testing/snapshots/bindings_output/imports/deconstruction/v2/generated/0.4.11-success.txt @@ -15,9 +15,9 @@ Definitions (8): References (6): - Ref: ["Foo" @ main.sol:1:9] -> #3 - Ref: ["Bar" @ main.sol:2:9] -> #1 -- Ref: ["Foo" @ main.sol:6:16] -> #3 +- Ref: ["Foo" @ main.sol:6:16] -> #5 - Ref: ["foo" @ main.sol:6:20] -> #4 -- Ref: ["LocalBar" @ main.sol:6:28] -> #1 +- Ref: ["LocalBar" @ main.sol:6:28] -> #6 - Ref: ["bar" @ main.sol:6:37] -> #2 ------------------------------------------------------------------------ @@ -74,11 +74,11 @@ Bindings: │ ╰─── name: 8 6 │ return Foo.foo() + LocalBar.bar(); │ ─┬─ ─┬─ ────┬─── ─┬─ - │ ╰──────────────────────── ref: 3 + │ ╰──────────────────────── ref: 5 │ │ │ │ │ ╰──────────────────── ref: 4 │ │ │ - │ ╰───────── ref: 1 + │ ╰───────── ref: 6 │ │ │ ╰─── ref: 2 ───╯ diff --git a/crates/solidity/testing/snapshots/bindings_output/modifiers/imported/v2/generated/0.4.11-success.txt b/crates/solidity/testing/snapshots/bindings_output/modifiers/imported/v2/generated/0.4.11-success.txt index f6a1b753f7..eb54cc7f8b 100644 --- a/crates/solidity/testing/snapshots/bindings_output/modifiers/imported/v2/generated/0.4.11-success.txt +++ b/crates/solidity/testing/snapshots/bindings_output/modifiers/imported/v2/generated/0.4.11-success.txt @@ -12,8 +12,8 @@ Definitions (5): References (5): - Ref: ["_" @ lib.sol:3:9] -> built-in - Ref: ["Base" @ main.sol:1:9] -> #1 -- Ref: ["Base" @ main.sol:3:18] -> #1 -- Ref: ["Base" @ main.sol:4:28] -> #1 +- Ref: ["Base" @ main.sol:3:18] -> #3 +- Ref: ["Base" @ main.sol:4:28] -> #3 - Ref: ["beforeRun" @ main.sol:4:33] -> #2 ------------------------------------------------------------------------ @@ -51,12 +51,12 @@ Bindings: │ ──┬─ ──┬─ │ ╰─────────── name: 4 │ │ - │ ╰─── ref: 1 + │ ╰─── ref: 3 4 │ function test() public Base.beforeRun { │ ──┬─ ──┬─ ────┬──── │ ╰─────────────────────────── name: 5 │ │ │ - │ ╰───────────── ref: 1 + │ ╰───────────── ref: 3 │ │ │ ╰────── ref: 2 ───╯ diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.4.11-failure.txt b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.4.11-failure.txt index d719ba4b97..53b5d43789 100644 --- a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.4.11-failure.txt +++ b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.4.11-failure.txt @@ -23,7 +23,7 @@ Definitions (4): References (4): - Ref: ["Counter" @ main.sol:1:9] -> unresolved -- Ref: ["Counter" @ main.sol:4:19] -> unresolved +- Ref: ["Counter" @ main.sol:4:19] -> #1 - Ref: ["c" @ main.sol:5:9] -> #4 - Ref: ["increment" @ main.sol:5:11] -> unresolved @@ -53,7 +53,7 @@ Bindings: │ ──┬─ ───┬─── ┬ │ ╰──────────────────── name: 3 │ │ │ - │ ╰────────────── unresolved + │ ╰────────────── ref: 1 │ │ │ ╰── name: 4 5 │ c.increment(); diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.6.0-failure.txt b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.6.0-failure.txt index d80cc2d3a6..4b6a9e935d 100644 --- a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.6.0-failure.txt +++ b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.6.0-failure.txt @@ -25,7 +25,7 @@ Definitions (6): References (4): - Ref: ["Counter" @ main.sol:1:9] -> #1 -- Ref: ["Counter" @ main.sol:4:19] -> #1 +- Ref: ["Counter" @ main.sol:4:19] -> #3 - Ref: ["c" @ main.sol:5:9] -> #6 - Ref: ["increment" @ main.sol:5:11] -> unresolved @@ -64,7 +64,7 @@ Bindings: │ ──┬─ ───┬─── ┬ │ ╰──────────────────── name: 5 │ │ │ - │ ╰────────────── ref: 1 + │ ╰────────────── ref: 3 │ │ │ ╰── name: 6 5 │ c.increment(); diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.7.1-failure.txt b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.7.1-failure.txt index 93088c2bf2..046c49a84e 100644 --- a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.7.1-failure.txt +++ b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.7.1-failure.txt @@ -27,7 +27,7 @@ Definitions (8): References (5): - Ref: ["Counter" @ counter.sol:5:20] -> #1 - Ref: ["Counter" @ main.sol:1:9] -> #1 -- Ref: ["Counter" @ main.sol:4:19] -> #1 +- Ref: ["Counter" @ main.sol:4:19] -> #5 - Ref: ["c" @ main.sol:5:9] -> #8 - Ref: ["increment" @ main.sol:5:11] -> unresolved @@ -74,7 +74,7 @@ Bindings: │ ──┬─ ───┬─── ┬ │ ╰──────────────────── name: 7 │ │ │ - │ ╰────────────── ref: 1 + │ ╰────────────── ref: 5 │ │ │ ╰── name: 8 5 │ c.increment(); diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.7.4-failure.txt b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.7.4-failure.txt index 89dd025fb5..5f98c4791e 100644 --- a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.7.4-failure.txt +++ b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.7.4-failure.txt @@ -27,7 +27,7 @@ Definitions (8): References (5): - Ref: ["Counter" @ counter.sol:5:20] -> #1 - Ref: ["Counter" @ main.sol:1:9] -> #1 -- Ref: ["Counter" @ main.sol:4:19] -> #1 +- Ref: ["Counter" @ main.sol:4:19] -> #5 - Ref: ["c" @ main.sol:5:9] -> #8 - Ref: ["increment" @ main.sol:5:11] -> unresolved @@ -74,7 +74,7 @@ Bindings: │ ──┬─ ───┬─── ┬ │ ╰──────────────────── name: 7 │ │ │ - │ ╰────────────── ref: 1 + │ ╰────────────── ref: 5 │ │ │ ╰── name: 8 5 │ c.increment(); diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.0-failure.txt b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.0-failure.txt index 68922816a2..4f600ff504 100644 --- a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.0-failure.txt +++ b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.0-failure.txt @@ -27,7 +27,7 @@ Definitions (8): References (5): - Ref: ["Counter" @ counter.sol:5:20] -> #1 - Ref: ["Counter" @ main.sol:1:9] -> #1 -- Ref: ["Counter" @ main.sol:4:19] -> #1 +- Ref: ["Counter" @ main.sol:4:19] -> #5 - Ref: ["c" @ main.sol:5:9] -> #8 - Ref: ["increment" @ main.sol:5:11] -> unresolved @@ -74,7 +74,7 @@ Bindings: │ ──┬─ ───┬─── ┬ │ ╰──────────────────── name: 7 │ │ │ - │ ╰────────────── ref: 1 + │ ╰────────────── ref: 5 │ │ │ ╰── name: 8 5 │ c.increment(); diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.13-success.txt b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.13-success.txt index b09e230ebb..dd017ce145 100644 --- a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.13-success.txt +++ b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.13-success.txt @@ -17,7 +17,7 @@ References (7): - Ref: ["increment" @ counter.sol:7:8] -> #3 - Ref: ["Counter" @ counter.sol:7:23] -> #1 - Ref: ["Counter" @ main.sol:1:9] -> #1 -- Ref: ["Counter" @ main.sol:4:19] -> #1 +- Ref: ["Counter" @ main.sol:4:19] -> #5 - Ref: ["c" @ main.sol:5:9] -> #8 - Ref: ["increment" @ main.sol:5:11] -> #3 @@ -70,7 +70,7 @@ Bindings: │ ──┬─ ───┬─── ┬ │ ╰──────────────────── name: 7 │ │ │ - │ ╰────────────── ref: 1 + │ ╰────────────── ref: 5 │ │ │ ╰── name: 8 5 │ c.increment(); diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.4-failure.txt b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.4-failure.txt index 62ab71f357..fbad2f2c88 100644 --- a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.4-failure.txt +++ b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.4-failure.txt @@ -27,7 +27,7 @@ Definitions (8): References (5): - Ref: ["Counter" @ counter.sol:5:20] -> #1 - Ref: ["Counter" @ main.sol:1:9] -> #1 -- Ref: ["Counter" @ main.sol:4:19] -> #1 +- Ref: ["Counter" @ main.sol:4:19] -> #5 - Ref: ["c" @ main.sol:5:9] -> #8 - Ref: ["increment" @ main.sol:5:11] -> unresolved @@ -74,7 +74,7 @@ Bindings: │ ──┬─ ───┬─── ┬ │ ╰──────────────────── name: 7 │ │ │ - │ ╰────────────── ref: 1 + │ ╰────────────── ref: 5 │ │ │ ╰── name: 8 5 │ c.increment(); diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.8-failure.txt b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.8-failure.txt index 9059385c90..f84a95f78e 100644 --- a/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.8-failure.txt +++ b/crates/solidity/testing/snapshots/bindings_output/using/global/v2/generated/0.8.8-failure.txt @@ -27,7 +27,7 @@ Definitions (8): References (5): - Ref: ["Counter" @ counter.sol:5:20] -> #1 - Ref: ["Counter" @ main.sol:1:9] -> #1 -- Ref: ["Counter" @ main.sol:4:19] -> #1 +- Ref: ["Counter" @ main.sol:4:19] -> #5 - Ref: ["c" @ main.sol:5:9] -> #8 - Ref: ["increment" @ main.sol:5:11] -> unresolved @@ -74,7 +74,7 @@ Bindings: │ ──┬─ ───┬─── ┬ │ ╰──────────────────── name: 7 │ │ │ - │ ╰────────────── ref: 1 + │ ╰────────────── ref: 5 │ │ │ ╰── name: 8 5 │ c.increment(); diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global_multi_file/v2/generated/0.8.13-success.txt b/crates/solidity/testing/snapshots/bindings_output/using/global_multi_file/v2/generated/0.8.13-success.txt index e0e7893b4b..9e9e8d1792 100644 --- a/crates/solidity/testing/snapshots/bindings_output/using/global_multi_file/v2/generated/0.8.13-success.txt +++ b/crates/solidity/testing/snapshots/bindings_output/using/global_multi_file/v2/generated/0.8.13-success.txt @@ -20,12 +20,12 @@ References (13): - Ref: ["Lib" @ main.sol:7:7] -> #2 - Ref: ["a" @ main.sol:11:9] -> #7 - Ref: ["nop" @ main.sol:11:11] -> #3 -- Ref: ["foo" @ main.sol:12:9] -> #10 +- Ref: ["foo" @ main.sol:12:9] -> #1 - Ref: ["a" @ main.sol:12:13] -> #7 - Ref: ["nop" @ main.sol:12:16] -> #3 - Ref: ["a" @ main.sol:17:5] -> #9 - Ref: ["nop" @ main.sol:17:7] -> #3 -- Ref: ["foo" @ main.sol:18:5] -> #10 +- Ref: ["foo" @ main.sol:18:5] -> #1 - Ref: ["a" @ main.sol:18:9] -> #9 - Ref: ["nop" @ main.sol:18:12] -> #3 - Ref: ["a" @ other.sol:2:12] -> #11 @@ -73,7 +73,7 @@ Bindings: │ ╰─── ref: 3 12 │ foo(a).nop(); │ ─┬─ ┬ ─┬─ - │ ╰────────── ref: 10 + │ ╰────────── ref: 1 │ │ │ │ ╰─────── ref: 7 │ │ @@ -91,7 +91,7 @@ Bindings: │ ╰─── ref: 3 18 │ foo(a).nop(); │ ─┬─ ┬ ─┬─ - │ ╰────────── ref: 10 + │ ╰────────── ref: 1 │ │ │ │ ╰─────── ref: 9 │ │ diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.4.11-failure.txt b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.4.11-failure.txt index 224ea19049..91c47542c6 100644 --- a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.4.11-failure.txt +++ b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.4.11-failure.txt @@ -22,7 +22,7 @@ Definitions (4): References (3): - Ref: ["FOO" @ main.sol:1:9] -> unresolved - Ref: ["add" @ main.sol:6:22] -> built-in -- Ref: ["FOO" @ main.sol:6:26] -> unresolved +- Ref: ["FOO" @ main.sol:6:26] -> #1 ------------------------------------------------------------------------ @@ -56,5 +56,5 @@ Bindings: │ │ │ │ ╰─────── built-in │ │ - │ ╰─── unresolved + │ ╰─── ref: 1 ───╯ diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.6.0-failure.txt b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.6.0-failure.txt index 36b7966f29..407795836b 100644 --- a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.6.0-failure.txt +++ b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.6.0-failure.txt @@ -22,7 +22,7 @@ Definitions (4): References (3): - Ref: ["FOO" @ main.sol:1:9] -> unresolved - Ref: ["add" @ main.sol:6:22] -> built-in -- Ref: ["FOO" @ main.sol:6:26] -> unresolved +- Ref: ["FOO" @ main.sol:6:26] -> #1 ------------------------------------------------------------------------ @@ -56,5 +56,5 @@ Bindings: │ │ │ │ ╰─────── built-in │ │ - │ ╰─── unresolved + │ ╰─── ref: 1 ───╯ diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.7.1-failure.txt b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.7.1-failure.txt index 8146cc9645..0f7ee10dbc 100644 --- a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.7.1-failure.txt +++ b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.7.1-failure.txt @@ -22,7 +22,7 @@ Definitions (4): References (3): - Ref: ["FOO" @ main.sol:1:9] -> unresolved - Ref: ["add" @ main.sol:6:22] -> built-in -- Ref: ["FOO" @ main.sol:6:26] -> unresolved +- Ref: ["FOO" @ main.sol:6:26] -> #1 ------------------------------------------------------------------------ @@ -56,5 +56,5 @@ Bindings: │ │ │ │ ╰─────── built-in │ │ - │ ╰─── unresolved + │ ╰─── ref: 1 ───╯ diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.7.4-success.txt b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.7.4-success.txt index 0ab03fa044..48dfa9d5ba 100644 --- a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.7.4-success.txt +++ b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/v2/generated/0.7.4-success.txt @@ -12,7 +12,7 @@ Definitions (5): References (3): - Ref: ["FOO" @ main.sol:1:9] -> #1 - Ref: ["add" @ main.sol:6:22] -> built-in -- Ref: ["FOO" @ main.sol:6:26] -> #1 +- Ref: ["FOO" @ main.sol:6:26] -> #2 ------------------------------------------------------------------------ @@ -52,5 +52,5 @@ Bindings: │ │ │ │ ╰─────── built-in │ │ - │ ╰─── ref: 1 + │ ╰─── ref: 2 ───╯ diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/imported_undefined_symbol/v2/generated/0.4.11-failure.txt b/crates/solidity/testing/snapshots/bindings_output/yul/imported_undefined_symbol/v2/generated/0.4.11-failure.txt index afd773b0ec..23059b2914 100644 --- a/crates/solidity/testing/snapshots/bindings_output/yul/imported_undefined_symbol/v2/generated/0.4.11-failure.txt +++ b/crates/solidity/testing/snapshots/bindings_output/yul/imported_undefined_symbol/v2/generated/0.4.11-failure.txt @@ -14,8 +14,8 @@ References (5): - Ref: ["slot" @ input.sol:1:10] -> unresolved - Ref: ["value" @ input.sol:7:13] -> #4 - Ref: ["sload" @ input.sol:7:22] -> built-in -- Ref: ["slot" @ input.sol:7:28] -> unresolved -- Ref: ["slot" @ input.sol:12:22] -> unresolved +- Ref: ["slot" @ input.sol:7:28] -> #1 +- Ref: ["slot" @ input.sol:12:22] -> #1 ------------------------------------------------------------------------ @@ -48,7 +48,7 @@ Bindings: │ │ │ │ ╰───────── built-in │ │ - │ ╰─── unresolved + │ ╰─── ref: 1 │ 11 │ function useSlotInSolidity() public { │ ────────┬──────── @@ -57,5 +57,5 @@ Bindings: │ ──┬── ──┬─ │ ╰─────────── name: 6 │ │ - │ ╰─── unresolved + │ ╰─── ref: 1 ────╯ From 67d2ca7e78167f7979268b99fb16e6231249150a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Mon, 19 Jan 2026 14:44:06 -0500 Subject: [PATCH 2/8] Add test cases differences with the stack graph binder --- .../deconstruction/diff/generated/0.4.11-success-diff.txt | 4 ++-- .../imported/diff/generated/0.4.11-success-diff.txt | 4 ++-- .../using/global/diff/generated/0.4.11-failure-same.txt | 3 +++ .../using/global/diff/generated/0.6.0-failure-diff.txt | 2 +- .../{0.4.11-failure-diff.txt => 0.7.1-failure-diff.txt} | 2 +- .../diff/generated/0.8.13-success-diff.txt | 4 ++-- .../diff/generated/0.4.11-failure-diff.txt | 5 ----- .../diff/generated/0.4.11-failure-same.txt | 3 +++ .../diff/generated/0.7.4-success-diff.txt | 2 +- .../diff/generated/0.4.11-failure-diff.txt | 6 ------ .../diff/generated/0.4.11-failure-same.txt | 3 +++ 11 files changed, 18 insertions(+), 20 deletions(-) create mode 100644 crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.4.11-failure-same.txt rename crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/{0.4.11-failure-diff.txt => 0.7.1-failure-diff.txt} (61%) delete mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/diff/generated/0.4.11-failure-diff.txt create mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/diff/generated/0.4.11-failure-same.txt delete mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/imported_undefined_symbol/diff/generated/0.4.11-failure-diff.txt create mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/imported_undefined_symbol/diff/generated/0.4.11-failure-same.txt diff --git a/crates/solidity/testing/snapshots/bindings_output/imports/deconstruction/diff/generated/0.4.11-success-diff.txt b/crates/solidity/testing/snapshots/bindings_output/imports/deconstruction/diff/generated/0.4.11-success-diff.txt index e2d6fabc7c..c1e947c815 100644 --- a/crates/solidity/testing/snapshots/bindings_output/imports/deconstruction/diff/generated/0.4.11-success-diff.txt +++ b/crates/solidity/testing/snapshots/bindings_output/imports/deconstruction/diff/generated/0.4.11-success-diff.txt @@ -1,6 +1,6 @@ # This file is generated automatically by infrastructure scripts. Please don't edit by hand. -Ref: ["Foo" @ main.sol:6:16] -> #3 resolved uniquely but resolved ambiguously in stack graph output -Ref: ["LocalBar" @ main.sol:6:28] -> #1 resolved uniquely but resolved ambiguously in stack graph output +Ref: ["Foo" @ main.sol:6:16] -> #5 resolved uniquely but resolved ambiguously in stack graph output +Ref: ["LocalBar" @ main.sol:6:28] -> #6 resolved uniquely but resolved ambiguously in stack graph output Definitions and/or references from binding graph and new binder DIFFER diff --git a/crates/solidity/testing/snapshots/bindings_output/modifiers/imported/diff/generated/0.4.11-success-diff.txt b/crates/solidity/testing/snapshots/bindings_output/modifiers/imported/diff/generated/0.4.11-success-diff.txt index 07c6d7def5..8d5cd9be80 100644 --- a/crates/solidity/testing/snapshots/bindings_output/modifiers/imported/diff/generated/0.4.11-success-diff.txt +++ b/crates/solidity/testing/snapshots/bindings_output/modifiers/imported/diff/generated/0.4.11-success-diff.txt @@ -1,6 +1,6 @@ # This file is generated automatically by infrastructure scripts. Please don't edit by hand. -Ref: ["Base" @ main.sol:3:18] -> #1 resolved uniquely but resolved ambiguously in stack graph output -Ref: ["Base" @ main.sol:4:28] -> #1 resolved uniquely but resolved ambiguously in stack graph output +Ref: ["Base" @ main.sol:3:18] -> #3 resolved uniquely but resolved ambiguously in stack graph output +Ref: ["Base" @ main.sol:4:28] -> #3 resolved uniquely but resolved ambiguously in stack graph output Definitions and/or references from binding graph and new binder DIFFER diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.4.11-failure-same.txt b/crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.4.11-failure-same.txt new file mode 100644 index 0000000000..11b00e3bf7 --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.4.11-failure-same.txt @@ -0,0 +1,3 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +No differences between binding graph and new binder definitions or references diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.6.0-failure-diff.txt b/crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.6.0-failure-diff.txt index dce909f98c..e873ef0cd7 100644 --- a/crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.6.0-failure-diff.txt +++ b/crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.6.0-failure-diff.txt @@ -1,5 +1,5 @@ # This file is generated automatically by infrastructure scripts. Please don't edit by hand. -Ref: ["Counter" @ main.sol:4:19] -> #1 resolved uniquely but resolved ambiguously in stack graph output +Ref: ["Counter" @ main.sol:4:19] -> #3 resolved uniquely but resolved ambiguously in stack graph output Definitions and/or references from binding graph and new binder DIFFER diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.4.11-failure-diff.txt b/crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.7.1-failure-diff.txt similarity index 61% rename from crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.4.11-failure-diff.txt rename to crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.7.1-failure-diff.txt index 1a105cdee3..ed383f79c5 100644 --- a/crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.4.11-failure-diff.txt +++ b/crates/solidity/testing/snapshots/bindings_output/using/global/diff/generated/0.7.1-failure-diff.txt @@ -1,5 +1,5 @@ # This file is generated automatically by infrastructure scripts. Please don't edit by hand. -reference `Counter` at main.sol:4:19 failed to resolve in new binder +Ref: ["Counter" @ main.sol:4:19] -> #5 resolved uniquely but resolved ambiguously in stack graph output Definitions and/or references from binding graph and new binder DIFFER diff --git a/crates/solidity/testing/snapshots/bindings_output/using/global_multi_file/diff/generated/0.8.13-success-diff.txt b/crates/solidity/testing/snapshots/bindings_output/using/global_multi_file/diff/generated/0.8.13-success-diff.txt index d1f6aea732..911d2c07db 100644 --- a/crates/solidity/testing/snapshots/bindings_output/using/global_multi_file/diff/generated/0.8.13-success-diff.txt +++ b/crates/solidity/testing/snapshots/bindings_output/using/global_multi_file/diff/generated/0.8.13-success-diff.txt @@ -1,6 +1,6 @@ # This file is generated automatically by infrastructure scripts. Please don't edit by hand. -Ref: ["foo" @ main.sol:12:9] -> #10 resolved uniquely but resolved ambiguously in stack graph output -Ref: ["foo" @ main.sol:18:5] -> #10 resolved uniquely but resolved ambiguously in stack graph output +Ref: ["foo" @ main.sol:12:9] -> #1 resolved uniquely but resolved ambiguously in stack graph output +Ref: ["foo" @ main.sol:18:5] -> #1 resolved uniquely but resolved ambiguously in stack graph output Definitions and/or references from binding graph and new binder DIFFER diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/diff/generated/0.4.11-failure-diff.txt b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/diff/generated/0.4.11-failure-diff.txt deleted file mode 100644 index 4a07869fe9..0000000000 --- a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/diff/generated/0.4.11-failure-diff.txt +++ /dev/null @@ -1,5 +0,0 @@ -# This file is generated automatically by infrastructure scripts. Please don't edit by hand. - -reference `FOO` at main.sol:6:26 failed to resolve in new binder - -Definitions and/or references from binding graph and new binder DIFFER diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/diff/generated/0.4.11-failure-same.txt b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/diff/generated/0.4.11-failure-same.txt new file mode 100644 index 0000000000..11b00e3bf7 --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/diff/generated/0.4.11-failure-same.txt @@ -0,0 +1,3 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +No differences between binding graph and new binder definitions or references diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/diff/generated/0.7.4-success-diff.txt b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/diff/generated/0.7.4-success-diff.txt index a809df3230..0b0ed17697 100644 --- a/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/diff/generated/0.7.4-success-diff.txt +++ b/crates/solidity/testing/snapshots/bindings_output/yul/imported_deconstructed_constants/diff/generated/0.7.4-success-diff.txt @@ -1,5 +1,5 @@ # This file is generated automatically by infrastructure scripts. Please don't edit by hand. -Ref: ["FOO" @ main.sol:6:26] -> #1 resolved uniquely but resolved ambiguously in stack graph output +Ref: ["FOO" @ main.sol:6:26] -> #2 resolved uniquely but resolved ambiguously in stack graph output Definitions and/or references from binding graph and new binder DIFFER diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/imported_undefined_symbol/diff/generated/0.4.11-failure-diff.txt b/crates/solidity/testing/snapshots/bindings_output/yul/imported_undefined_symbol/diff/generated/0.4.11-failure-diff.txt deleted file mode 100644 index e1013d5ef9..0000000000 --- a/crates/solidity/testing/snapshots/bindings_output/yul/imported_undefined_symbol/diff/generated/0.4.11-failure-diff.txt +++ /dev/null @@ -1,6 +0,0 @@ -# This file is generated automatically by infrastructure scripts. Please don't edit by hand. - -reference `slot` at input.sol:7:28 failed to resolve in new binder -reference `slot` at input.sol:12:22 failed to resolve in new binder - -Definitions and/or references from binding graph and new binder DIFFER diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/imported_undefined_symbol/diff/generated/0.4.11-failure-same.txt b/crates/solidity/testing/snapshots/bindings_output/yul/imported_undefined_symbol/diff/generated/0.4.11-failure-same.txt new file mode 100644 index 0000000000..11b00e3bf7 --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/yul/imported_undefined_symbol/diff/generated/0.4.11-failure-same.txt @@ -0,0 +1,3 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +No differences between binding graph and new binder definitions or references From 1ae9c47f7684f02be9fcea4184934607ca5d692c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Mon, 19 Jan 2026 17:12:45 -0500 Subject: [PATCH 3/8] Add `Identifier::resolve_to_immediate_definition` to avoid following imports --- .../ir/ast/node_extensions/identifiers.rs | 46 ++++++++++++++++++- .../cargo/tests/src/backend/semantic/ast.rs | 38 +++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs b/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs index c66843ae98..92b5dccc03 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs @@ -35,7 +35,7 @@ impl IdentifierStruct { .is_some() } - // Attempts to resolve the identifier path to a definition, following symbol + // Attempts to resolve the identifier to a definition, following symbol // aliases (import deconstructions). This only makes sense if // `is_reference()` is true. pub fn resolve_to_definition(&self) -> Option { @@ -45,6 +45,19 @@ impl IdentifierStruct { Some(Definition::create(definition_id, &self.semantic)) } + // Attempts to resolve the identifier to an immediate definition, without + // following symbol aliases, possibly returning import deconstruction + // symbols. If the symbol is directly defined, this is equivalent to + // `resolve_to_definition`. This only makes sense if `is_reference()` is + // true. + pub fn resolve_to_immediate_definition(&self) -> Option { + let definition_id = self + .semantic + .resolve_reference_identifier_to_immediate_definition_id(self.ir_node.id())?; + Some(Definition::create(definition_id, &self.semantic)) + } + + /// Returns `true` if the identifier itself is a definition (eg. an enum member) pub fn is_definition(&self) -> bool { self.semantic .binder() @@ -113,6 +126,14 @@ impl Reference { } } } + + pub fn resolve_to_immediate_definition(&self) -> Option { + match self { + Reference::Identifier(identifier) | Reference::YulIdentifier(identifier) => { + identifier.resolve_to_immediate_definition() + } + } + } } impl SemanticAnalysis { @@ -137,6 +158,16 @@ impl SemanticAnalysis { .follow_symbol_aliases(&reference.resolution) .as_definition_id() } + + fn resolve_reference_identifier_to_immediate_definition_id( + &self, + node_id: NodeId, + ) -> Option { + let reference = self + .binder() + .find_reference_by_identifier_node_id(node_id)?; + reference.resolution.as_definition_id() + } } impl IdentifierPathStruct { @@ -157,4 +188,17 @@ impl IdentifierPathStruct { .resolve_reference_identifier_to_definition_id(ir_node.id())?; Some(Definition::create(definition_id, &self.semantic)) } + + // Attempts to resolve the identifier path to an immediate definition, + // without following symbol aliases, possibly returning import + // deconstruction symbols. If the symbol is directly defined, this is + // equivalent to `resolve_to_definition`. This only makes sense if + // `is_reference()` is true. + pub fn resolve_to_immediate_definition(&self) -> Option { + let ir_node = self.ir_nodes.last()?; + let definition_id = self + .semantic + .resolve_reference_identifier_to_immediate_definition_id(ir_node.id())?; + Some(Definition::create(definition_id, &self.semantic)) + } } diff --git a/crates/solidity/outputs/cargo/tests/src/backend/semantic/ast.rs b/crates/solidity/outputs/cargo/tests/src/backend/semantic/ast.rs index a89a8844f1..d9decb30c4 100644 --- a/crates/solidity/outputs/cargo/tests/src/backend/semantic/ast.rs +++ b/crates/solidity/outputs/cargo/tests/src/backend/semantic/ast.rs @@ -89,3 +89,41 @@ fn test_text_offsets() -> Result<()> { Ok(()) } + +#[test] +fn test_resolve_to_immediate_definition() -> Result<()> { + let unit = build_compilation_unit()?; + let semantic = unit.semantic_analysis(); + + let counter = semantic + .find_contract_by_name("Counter") + .expect("contract is found"); + let counter_bases: Vec<_> = counter + .inheritance_types() + .iter() + .map(|base_type| base_type.type_name()) + .collect(); + assert_eq!(counter_bases.len(), 2); + + assert_eq!(counter_bases[0].unparse(), "Ownable"); + assert!(matches!( + counter_bases[0].resolve_to_definition(), + Some(ast::Definition::Contract(_)) + )); + assert!(matches!( + counter_bases[0].resolve_to_immediate_definition(), + Some(ast::Definition::ImportedSymbol(_)) + )); + + assert_eq!(counter_bases[1].unparse(), "Activatable"); + assert!(matches!( + counter_bases[1].resolve_to_definition(), + Some(ast::Definition::Contract(_)) + )); + assert!(matches!( + counter_bases[1].resolve_to_immediate_definition(), + Some(ast::Definition::ImportedSymbol(_)) + )); + + Ok(()) +} From 79dee04d6d4da3b6c667183c6622ab3625836628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Wed, 21 Jan 2026 14:53:39 -0500 Subject: [PATCH 4/8] Update crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs Co-authored-by: Teodoro Freund --- .../crate/src/backend/ir/ast/node_extensions/identifiers.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs b/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs index 92b5dccc03..934d9cae00 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs @@ -35,9 +35,9 @@ impl IdentifierStruct { .is_some() } - // Attempts to resolve the identifier to a definition, following symbol - // aliases (import deconstructions). This only makes sense if - // `is_reference()` is true. + /// Attempts to resolve the identifier to a definition, following symbol + /// aliases (import deconstructions). This only makes sense if + /// `is_reference()` is true. pub fn resolve_to_definition(&self) -> Option { let definition_id = self .semantic From 2108345af42136324c18fa8040e8b5287f5acc72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Wed, 21 Jan 2026 16:30:16 -0500 Subject: [PATCH 5/8] Clarify comment on following symbol aliases --- .../crate/src/backend/passes/p3_linearise_contracts/mod.rs | 5 ++++- .../src/backend/passes/p4_type_definitions/resolution.rs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/solidity/outputs/cargo/crate/src/backend/passes/p3_linearise_contracts/mod.rs b/crates/solidity/outputs/cargo/crate/src/backend/passes/p3_linearise_contracts/mod.rs index c809c51fcc..74e162770a 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/passes/p3_linearise_contracts/mod.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/passes/p3_linearise_contracts/mod.rs @@ -128,7 +128,10 @@ impl<'a> Pass<'a> { // Unless we used namespace resolution and in order to continue // resolving the identifier path, we should ensure we've followed - // through any symbol alias (ie. import deconstruction symbol) + // through any symbol alias (ie. import deconstruction symbol). This + // is not needed for namespaced resolution because there cannot be + // import directives inside contracts, interfaces or libraries which + // changes the lookup mode (see below). let resolution = if use_lexical_resolution { self.binder.follow_symbol_aliases(&resolution) } else { diff --git a/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/resolution.rs b/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/resolution.rs index 94d48ca321..40a06fb28f 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/resolution.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/resolution.rs @@ -38,7 +38,10 @@ impl Pass<'_> { // Unless we used namespace resolution and in order to continue // resolving the identifier path, we should ensure we've followed - // through any symbol alias (ie. import deconstruction symbol) + // through any symbol alias (ie. import deconstruction symbol). This + // is not needed for namespaced resolution because there cannot be + // import directives inside contracts, interfaces or libraries which + // changes the lookup mode (see below). let resolution = if use_lexical_resolution { self.binder.follow_symbol_aliases(&resolution) } else { From 66b4f52ea5a1b7b379b1e09a8900eab0806c87fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Thu, 22 Jan 2026 10:44:05 -0500 Subject: [PATCH 6/8] Rework documentation comments --- .../ir/ast/node_extensions/identifiers.rs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs b/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs index 934d9cae00..00cdbf07d6 100644 --- a/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs +++ b/crates/solidity/outputs/cargo/crate/src/backend/ir/ast/node_extensions/identifiers.rs @@ -36,8 +36,8 @@ impl IdentifierStruct { } /// Attempts to resolve the identifier to a definition, following symbol - /// aliases (import deconstructions). This only makes sense if - /// `is_reference()` is true. + /// aliases (import deconstructions). Returns `None` if the identifier is + /// not acting as a reference, or the reference cannot be resolved. pub fn resolve_to_definition(&self) -> Option { let definition_id = self .semantic @@ -45,11 +45,12 @@ impl IdentifierStruct { Some(Definition::create(definition_id, &self.semantic)) } - // Attempts to resolve the identifier to an immediate definition, without - // following symbol aliases, possibly returning import deconstruction - // symbols. If the symbol is directly defined, this is equivalent to - // `resolve_to_definition`. This only makes sense if `is_reference()` is - // true. + /// Attempts to resolve the identifier to an immediate definition, without + /// following symbol aliases, possibly returning import deconstruction + /// symbols. If the identifier refers to a direct definition, this is + /// equivalent to `resolve_to_definition()`. Returns `None` if the + /// identifier is not acting as a reference, or the reference cannot be + /// resolved. pub fn resolve_to_immediate_definition(&self) -> Option { let definition_id = self .semantic @@ -179,8 +180,8 @@ impl IdentifierPathStruct { .join(".") } - // Attempts to resolve the identifier path to a definition, following symbol - // aliases (import deconstructions) + /// Attempts to resolve the identifier path to a definition, following + /// symbol aliases (import deconstructions). pub fn resolve_to_definition(&self) -> Option { let ir_node = self.ir_nodes.last()?; let definition_id = self @@ -189,11 +190,10 @@ impl IdentifierPathStruct { Some(Definition::create(definition_id, &self.semantic)) } - // Attempts to resolve the identifier path to an immediate definition, - // without following symbol aliases, possibly returning import - // deconstruction symbols. If the symbol is directly defined, this is - // equivalent to `resolve_to_definition`. This only makes sense if - // `is_reference()` is true. + /// Attempts to resolve the identifier path to an immediate definition, + /// without following symbol aliases, possibly returning import + /// deconstruction symbols. If the path refers to a direct definition, this + /// is equivalent to `resolve_to_definition`. pub fn resolve_to_immediate_definition(&self) -> Option { let ir_node = self.ir_nodes.last()?; let definition_id = self From 8587353a22b775282c4dd3ec60bacc91d7d86c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Thu, 22 Jan 2026 12:54:49 -0500 Subject: [PATCH 7/8] Add some more test cases for `resolve_to_definition{,immediately}` --- .../cargo/tests/src/backend/semantic/ast.rs | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/crates/solidity/outputs/cargo/tests/src/backend/semantic/ast.rs b/crates/solidity/outputs/cargo/tests/src/backend/semantic/ast.rs index d9decb30c4..cb7ffc79f4 100644 --- a/crates/solidity/outputs/cargo/tests/src/backend/semantic/ast.rs +++ b/crates/solidity/outputs/cargo/tests/src/backend/semantic/ast.rs @@ -1,7 +1,9 @@ use anyhow::Result; use slang_solidity::backend::semantic::ast; +use slang_solidity::utils::LanguageFacts; use crate::backend::sample::build_compilation_unit; +use crate::compilation::compilation_unit::build_compilation_unit_from_multi_part_file; #[test] fn test_ast_visitor() -> Result<()> { @@ -127,3 +129,95 @@ fn test_resolve_to_immediate_definition() -> Result<()> { Ok(()) } + +const CHAINED_SAMPLE: &str = r#" +// ---- path: first.sol +import {B2 as B1} from "second.sol"; +interface I1 {} +contract A1 is I1, B1 {} + +// ---- path: second.sol +import {B3 as B2} from "third.sol"; + +// ---- path: third.sol +contract B3 {} +"#; + +#[test] +fn test_resolve_to_immediate_resolves_to_direct_definition() -> Result<()> { + let unit = build_compilation_unit_from_multi_part_file( + &LanguageFacts::LATEST_VERSION, + CHAINED_SAMPLE, + )?; + let semantic = unit.semantic_analysis(); + + let a1 = semantic + .find_contract_by_name("A1") + .expect("contract is found"); + let i1_typename = a1 + .inheritance_types() + .iter() + .next() + .expect("there is at least one inheritance type") + .type_name(); + assert_eq!(i1_typename.unparse(), "I1"); + let Some(i1) = i1_typename.resolve_to_definition() else { + panic!("i1 can be resolved"); + }; + let Some(i1_immediate) = i1_typename.resolve_to_immediate_definition() else { + panic!("i1 can be resolved immediately"); + }; + + assert!(matches!( + (i1, i1_immediate), + (ast::Definition::Interface(_), ast::Definition::Interface(_)) + )); + + Ok(()) +} + +#[test] +fn test_chained_imports_resolution() -> Result<()> { + let unit = build_compilation_unit_from_multi_part_file( + &LanguageFacts::LATEST_VERSION, + CHAINED_SAMPLE, + )?; + let semantic = unit.semantic_analysis(); + + let a1 = semantic + .find_contract_by_name("A1") + .expect("contract is found"); + let b1_typename = a1 + .inheritance_types() + .iter() + .nth(1) + .expect("there are at least two inheritance types") + .type_name(); + assert_eq!(b1_typename.unparse(), "B1"); + + let b1 = b1_typename + .resolve_to_immediate_definition() + .expect("b1 base can be resolved"); + let ast::Definition::ImportedSymbol(b1_import) = b1 else { + panic!("b1 resolves to an import symbol"); + }; + + let b2 = b1_import + .name() + .resolve_to_immediate_definition() + .expect("b1 import can be resolved"); + let ast::Definition::ImportedSymbol(b2_import) = b2 else { + panic!("b2 resolves to an import symbol"); + }; + + let b3 = b2_import + .name() + .resolve_to_immediate_definition() + .expect("b2 import can be resolved"); + let ast::Definition::Contract(b3_contract) = b3 else { + panic!("b3 resolves to a contract"); + }; + assert_eq!(b3_contract.name().unparse(), "B3"); + + Ok(()) +} From bc40ee3f51cfa9bead85b34307b5cf1c1cdc789e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Fri, 30 Jan 2026 20:16:34 -0500 Subject: [PATCH 8/8] Move chained imports sample into fixtures --- .../src/backend/fixtures/chained_imports.rs | 28 +++++++++++++++++++ .../cargo/tests/src/backend/fixtures/mod.rs | 11 ++++++++ .../cargo/tests/src/backend/semantic/ast.rs | 25 ++--------------- 3 files changed, 41 insertions(+), 23 deletions(-) create mode 100644 crates/solidity/outputs/cargo/tests/src/backend/fixtures/chained_imports.rs diff --git a/crates/solidity/outputs/cargo/tests/src/backend/fixtures/chained_imports.rs b/crates/solidity/outputs/cargo/tests/src/backend/fixtures/chained_imports.rs new file mode 100644 index 0000000000..a7d61ec5e4 --- /dev/null +++ b/crates/solidity/outputs/cargo/tests/src/backend/fixtures/chained_imports.rs @@ -0,0 +1,28 @@ +use std::rc::Rc; + +use anyhow::Result; +use slang_solidity::compilation::CompilationUnit; +use slang_solidity::utils::LanguageFacts; + +use crate::compilation::compilation_unit::build_compilation_unit_from_multi_part_file; + +const CHAINED_SAMPLE: &str = r#" +// ---- path: first.sol +import {B2 as B1} from "second.sol"; +interface I1 {} +contract A1 is I1, B1 {} + +// ---- path: second.sol +import {B3 as B2} from "third.sol"; + +// ---- path: third.sol +contract B3 {} +"#; + +pub(crate) struct ChainedImports {} + +impl ChainedImports { + pub(crate) fn build_compilation_unit() -> Result> { + build_compilation_unit_from_multi_part_file(&LanguageFacts::LATEST_VERSION, CHAINED_SAMPLE) + } +} diff --git a/crates/solidity/outputs/cargo/tests/src/backend/fixtures/mod.rs b/crates/solidity/outputs/cargo/tests/src/backend/fixtures/mod.rs index a650747481..bfd7454fa2 100644 --- a/crates/solidity/outputs/cargo/tests/src/backend/fixtures/mod.rs +++ b/crates/solidity/outputs/cargo/tests/src/backend/fixtures/mod.rs @@ -1,11 +1,22 @@ use anyhow::Result; +mod chained_imports; mod counter; mod overrides; +pub(crate) use chained_imports::ChainedImports; pub(crate) use counter::Counter; pub(crate) use overrides::Overrides; +#[test] +fn test_build_chained_imports_fixture() -> Result<()> { + let unit = ChainedImports::build_compilation_unit()?; + let semantic_analysis = unit.semantic_analysis(); + assert_eq!(3, semantic_analysis.files().len()); + + Ok(()) +} + #[test] fn test_build_counter_fixture() -> Result<()> { let unit = Counter::build_compilation_unit()?; diff --git a/crates/solidity/outputs/cargo/tests/src/backend/semantic/ast.rs b/crates/solidity/outputs/cargo/tests/src/backend/semantic/ast.rs index b9a593998e..04b6b95827 100644 --- a/crates/solidity/outputs/cargo/tests/src/backend/semantic/ast.rs +++ b/crates/solidity/outputs/cargo/tests/src/backend/semantic/ast.rs @@ -1,9 +1,7 @@ use anyhow::Result; use slang_solidity::backend::semantic::ast; -use slang_solidity::utils::LanguageFacts; use crate::backend::fixtures; -use crate::compilation::compilation_unit::build_compilation_unit_from_multi_part_file; #[test] fn test_ast_visitor() -> Result<()> { @@ -130,25 +128,9 @@ fn test_resolve_to_immediate_definition() -> Result<()> { Ok(()) } -const CHAINED_SAMPLE: &str = r#" -// ---- path: first.sol -import {B2 as B1} from "second.sol"; -interface I1 {} -contract A1 is I1, B1 {} - -// ---- path: second.sol -import {B3 as B2} from "third.sol"; - -// ---- path: third.sol -contract B3 {} -"#; - #[test] fn test_resolve_to_immediate_resolves_to_direct_definition() -> Result<()> { - let unit = build_compilation_unit_from_multi_part_file( - &LanguageFacts::LATEST_VERSION, - CHAINED_SAMPLE, - )?; + let unit = fixtures::ChainedImports::build_compilation_unit()?; let semantic = unit.semantic_analysis(); let a1 = semantic @@ -178,10 +160,7 @@ fn test_resolve_to_immediate_resolves_to_direct_definition() -> Result<()> { #[test] fn test_chained_imports_resolution() -> Result<()> { - let unit = build_compilation_unit_from_multi_part_file( - &LanguageFacts::LATEST_VERSION, - CHAINED_SAMPLE, - )?; + let unit = fixtures::ChainedImports::build_compilation_unit()?; let semantic = unit.semantic_analysis(); let a1 = semantic