Skip to content

Commit

Permalink
Solidity binding fixes driven by Sanctuary (#1149)
Browse files Browse the repository at this point in the history
This PR contains fixes to bindings for issues that were found by trying
to resolve all references in Sanctuary, as well as test cases to verify
them. It also improves documentation of the rules and improvements
(renames and rearrangements) for readability. The built-in types are
also standardized with a PascalCase naming convention.

Most notably, it introduces extension scopes to support resolving
attached function set via `using` directives. These extension scopes
need to be accessible at any point during the resolution of a symbol
stack if the originating reference is located in a lexical scope which
is affected by a `using` directive. This forced a refactor of the
lexical scope node structure, introducing a new `.extended_scope`
available in nodes where references may need to resolve to attached
functions (ie. function bodies, constant initialization expressions,
etc.) Also, for Solidity < 0.7.0 `using` directives are inherited, so we
need to propagate the new extension scopes for all sub-contracts
relative to where the directive is located.

The extension scope mechanism is implemented using the _jump to scope_
and scope stack features of the stack graphs. The extended scope would
optionally push the extension scope for the current contract and then
continue resolution through the normal lexical scope. This effectively
doubles the search space in the graph when performing a resolution, and
this happens every time we inject a new extension scope to the scope
stack. This has the potential to exponentially increase the running
times and memory requirements. This is a known caveat which will be
addressed in a future PR.
  • Loading branch information
ggiraldez authored Dec 14, 2024
1 parent d497d73 commit 2ffc8f5
Show file tree
Hide file tree
Showing 228 changed files with 7,669 additions and 1,621 deletions.
19 changes: 14 additions & 5 deletions crates/metaslang/bindings/src/resolver/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::iter::once;

use metaslang_cst::kinds::KindTypes;
Expand Down Expand Up @@ -76,19 +76,28 @@ impl<'a, KT: KindTypes + 'static> Resolver<'a, KT> {
)
.expect("should never be cancelled");

let mut added_nodes = HashSet::new();
for reference_path in &reference_paths {
if reference_paths
.iter()
.all(|other| !other.shadows(&mut self.partials, reference_path))
let end_node = reference_path.end_node;

// Because of how we're using the scope stack to propagate dynamic
// scopes, we may get multiple results with different scope stack
// postconditions but reaching the exact same definition. We only
// care about the definition, so we check for uniqueness.
if !added_nodes.contains(&end_node)
&& reference_paths
.iter()
.all(|other| !other.shadows(&mut self.partials, reference_path))
{
self.results.push(ResolvedPath {
definition: self
.owner
.to_definition(reference_path.end_node)
.to_definition(end_node)
.expect("path to end in a definition node"),
partial_path: reference_path.clone(),
score: 0.0,
});
added_nodes.insert(end_node);
}
}
}
Expand Down
Loading

0 comments on commit 2ffc8f5

Please sign in to comment.