Skip to content

Commit f81efc7

Browse files
committed
Merge branch 'pr1118'
2 parents 6e77545 + 09ba026 commit f81efc7

3 files changed

Lines changed: 68 additions & 1 deletion

File tree

crates/sol-macro-expander/src/expand/contract.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,12 @@ struct ExpandData {
579579
min_data_len: usize,
580580
trait_: Ident,
581581
selectors: Vec<ExprArray<u8>>,
582+
/// Whether the builtin `#[sol(all_derives)]` traits can be derived on the
583+
/// generated enum. Computed from the underlying items' parameter types,
584+
/// because the variant type names may be synthetic (overloaded items get
585+
/// `_N` suffixes, call variants use `*Call` structs) and thus not
586+
/// resolvable as items.
587+
can_derive_builtin: bool,
582588
}
583589

584590
impl ExpandData {
@@ -645,6 +651,9 @@ impl ToExpand<'_> {
645651
.unwrap(),
646652
trait_: format_ident!("SolCall"),
647653
selectors: functions.iter().map(|f| cx.function_selector(f)).collect(),
654+
can_derive_builtin: functions
655+
.iter()
656+
.all(|f| f.parameters.types().all(|ty| cx.can_derive_builtin_traits(ty))),
648657
}
649658
}
650659

@@ -659,6 +668,9 @@ impl ToExpand<'_> {
659668
.unwrap(),
660669
trait_: format_ident!("SolError"),
661670
selectors: errors.iter().map(|e| cx.error_selector(e)).collect(),
671+
can_derive_builtin: errors.iter().all(|&error| {
672+
error.parameters.types().all(|ty| cx.can_derive_builtin_traits(ty))
673+
}),
662674
},
663675

664676
Self::Events(events) => {
@@ -676,6 +688,9 @@ impl ToExpand<'_> {
676688
.unwrap(),
677689
trait_: format_ident!("SolEvent"),
678690
selectors: events.iter().map(|e| cx.event_selector(e)).collect(),
691+
can_derive_builtin: events.iter().all(|&event| {
692+
event.parameters.iter().all(|p| cx.can_derive_builtin_traits(&p.ty))
693+
}),
679694
}
680695
}
681696
}
@@ -918,7 +933,7 @@ impl CallLikeExpander<'_> {
918933
assert!(selectors.iter().all(|s| s.array.len() == selector_len));
919934
let selector_type = quote!([u8; #selector_len]);
920935

921-
self.cx.type_derives(&mut attrs, types.iter().cloned().map(ast::Type::custom), false);
936+
self.cx.enum_derives(&mut attrs, data.can_derive_builtin);
922937
let trait_ = &data.trait_;
923938

924939
let mut tokens = quote! {

crates/sol-macro-expander/src/expand/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,26 @@ impl<'ast> ExpCtxt<'ast> {
726726
attrs.push(parse_quote! { #[derive(#(#derives), *)] });
727727
}
728728

729+
/// Like [`type_derives`](Self::type_derives), but for the generated `*Calls`
730+
/// / `*Errors` / `*Events` enums.
731+
///
732+
/// The enum variant types may be synthetic names that don't resolve as
733+
/// items (overloaded items get `_N` suffixes; call variants use `*Call`
734+
/// structs), so whether the builtin traits can be derived is precomputed
735+
/// from the underlying items' parameter types. Enums never derive
736+
/// `Default`.
737+
fn enum_derives(&self, attrs: &mut Vec<Attribute>, can_derive_builtin: bool) {
738+
if let Some(extra) = &self.attrs.extra_derives {
739+
if !extra.is_empty() {
740+
attrs.push(parse_quote! { #[derive(#(#extra),*)] });
741+
}
742+
}
743+
744+
if self.attrs.all_derives == Some(true) && can_derive_builtin {
745+
attrs.push(parse_quote! { #[derive(Debug, PartialEq, Eq, Hash)] });
746+
}
747+
}
748+
729749
/// Returns an error if any of the types in the parameters are unresolved.
730750
///
731751
/// Provides a better error message than an `unwrap` or `expect` when we

crates/sol-types/tests/derives.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,35 @@ fn test_extra_derives() {
9898
// Should not increase size since they're equal
9999
assert_eq!(calls_set.len(), 1);
100100
}
101+
102+
// Overloaded events (same name, different params) get suffixed variant names
103+
// (e.g. `Swap_0`, `Swap_1`). The generated `*Events` enum must still receive
104+
// the `#[sol(all_derives)]` traits. See alloy-rs/alloy#3856.
105+
#[test]
106+
#[allow(non_snake_case)]
107+
fn test_all_derives_overloaded_events() {
108+
sol! {
109+
#[sol(all_derives)]
110+
contract OverloadedEvents {
111+
event Swap(address indexed sender, uint256 amount0);
112+
event Swap(address indexed sender, address indexed to, int256 amount0, int256 amount1);
113+
}
114+
}
115+
116+
use OverloadedEvents::*;
117+
118+
let a =
119+
OverloadedEventsEvents::Swap_0(Swap_0 { sender: Address::ZERO, amount0: U256::from(1) });
120+
let b =
121+
OverloadedEventsEvents::Swap_0(Swap_0 { sender: Address::ZERO, amount0: U256::from(1) });
122+
123+
// Debug + PartialEq
124+
assert_eq!(a, b);
125+
let _ = format!("{a:?}");
126+
127+
// Hash + Eq
128+
let mut set = HashSet::new();
129+
set.insert(a);
130+
set.insert(b);
131+
assert_eq!(set.len(), 1);
132+
}

0 commit comments

Comments
 (0)