-
Notifications
You must be signed in to change notification settings - Fork 151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: correctly resolve duplicate struct names in json abi #690
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool, I believe this works and is easy to follow.
can we add another test case for foundry-rs/foundry#8444
imo we can ignore this edge case import {Struct as Struct2}
ptal @DaniPopes
/// various structs with such name have. | ||
#[derive(Debug, Default, Clone)] | ||
struct Collector<'a> { | ||
unique_struct_components: BTreeMap<&'a str, BTreeSet<Vec<&'a str>>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps worth using smallvec here for the Vec
because we only expect a few projections?
.map(move |(idx, components)| { | ||
let components = | ||
components.into_iter().map(ToString::to_string).collect::<Vec<_>>(); | ||
(components, format!("{name}{idx}")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we start at 0 here or at 1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
function overloads start with 0, so I've just made it similar
just noticed that functions are named as function_0
, function_1
, should we include underscore here as well?
/// A [crate::Visitor] implementation that collects a mapping from struct name to set of components | ||
/// various structs with such name have. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah okay, I understand how this works, first we traverse the abi and collect unique names and their paths
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really like renaming because this doesn't tackle the underlying problem that namespaces are not handled in sol!, e.g. this only fixes json input
I have a branch open where I make namespaced output work, but got stuck on weird compile errors https://github.com/alloy-rs/core/tree/dani/to-sol-contract-specifiers
/// structs. | ||
/// | ||
/// Namespace for global struct names is managed and in cases of duplicates structs are renamed. | ||
pub fn rename_internal_structs(&mut self) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think any of this should be exposed publicly, it should only be a sol! implentation detail
yeah, such approach indeed is more flexible current branch compiles fine for me, do you have more fixes for sol! as wip? from diff and a quick test it seems that updated |
It fails to compile in tests in crates/sol-types/tests/macros/sol/json.rs, but expanding the output and compiling it separately is fine It only handles the ToSol side, expanding libraries, but namespaces are not handled in the sol! internal representation, so function signatures are wrong Probably best to just continue that branch |
fyi moving |
one of the issues seems to be a limitation of function-level modules e.g. this code doesn't work fn test_fn() {
pub mod inner1 {
pub struct InnerStruct {}
}
pub mod inner2 {
use super::*;
fn some_fn() {
inner1::InnerStruct {};
}
}
} and it seems that there's no way to reach other modules defined inside of a function from inside of another module |
Motivation
Closes #660
Solution
I've added second abi preprocessing method
JsonAbi::rename_internal_structs
, which goes over ABI, resolves structs that have a same name but different components sets, and renames them into<struct name>0
,<struct name>1
, etcIt should be also possible to key them by
contract
instead, however, there are some edge cases related to aliases with such approach. E.g.import {Struct as Struct1} from "..."; import {Struct as Struct2} from "...";
will result in two different structs referenced asStruct
in ABI. Same is possible withLib.Struct
if differentLib
s are aliased.This edge case is kind of weird, so I am open to changing impl if we consider performance improvements worth it.
Also not sure if we want this to happen on the level of
JsonAbi::to_sol
instead of only forsol!
used codePR Checklist