Skip to content

Commit afa7bd4

Browse files
committed
fix(sol-macro): derive Default for dynamic arrays of non-Default elements
A dynamic Solidity array maps to Vec<T>, whose Default impl holds for any T. can_derive_default still required the element type to be Default for dynamic arrays, so a struct/error with a field like MyEnum[] lost its Default derive under #[sol(all_derives)] even though Vec<MyEnum>: Default. Only require the element to be Default (and length <= 32) for fixed-size arrays ([T; N]); dynamic arrays are always Default.
1 parent f81efc7 commit afa7bd4

2 files changed

Lines changed: 28 additions & 4 deletions

File tree

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,12 @@ impl ExpCtxt<'_> {
229229
/// Returns whether the given type can derive the [`Default`] trait.
230230
pub(crate) fn can_derive_default(&self, ty: &Type) -> bool {
231231
match ty {
232-
Type::Array(a) => {
233-
self.eval_array_size(a).is_none_or(|sz| sz <= MAX_SUPPORTED_ARRAY_LEN)
234-
&& self.can_derive_default(&a.ty)
235-
}
232+
Type::Array(a) => match self.eval_array_size(a) {
233+
// Dynamic arrays are `Vec<T>`, whose `Default` impl holds for any `T`.
234+
None => true,
235+
// Fixed arrays are `[T; N]`: `Default` needs `T: Default` and `N <= 32`.
236+
Some(sz) => sz <= MAX_SUPPORTED_ARRAY_LEN && self.can_derive_default(&a.ty),
237+
},
236238
Type::Tuple(tuple) => {
237239
if tuple.types.len() > MAX_SUPPORTED_TUPLE_LEN {
238240
false

crates/sol-types/tests/derives.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,25 @@ fn test_all_derives_overloaded_events() {
130130
set.insert(b);
131131
assert_eq!(set.len(), 1);
132132
}
133+
134+
// A dynamic array maps to `Vec<T>`, whose `Default` impl holds for any `T` (empty vec).
135+
// So a struct with a dynamic-array field of a non-`Default` element (an enum) should
136+
// still derive `Default` under `#[sol(all_derives)]`.
137+
#[test]
138+
fn test_default_dynamic_array_of_non_default_elem() {
139+
sol! {
140+
#[sol(all_derives)]
141+
contract DynArrDefault {
142+
enum E { A, B }
143+
struct S {
144+
E[] xs;
145+
uint256 n;
146+
}
147+
}
148+
}
149+
150+
use DynArrDefault::*;
151+
let s = S::default();
152+
assert!(s.xs.is_empty());
153+
assert_eq!(s.n, U256::ZERO);
154+
}

0 commit comments

Comments
 (0)