Summary
Support deriving traits even if a field of the struct/enum is an array of length >32 or a tuple of length >12.
Motivation
I have an FFI struct
pub struct usbmuxd_device_info_t {
pub handle: u32,
pub product_id: c_int,
pub udid: [c_char; 41], // <--
}
which cannot #[derive]
any of the built-in trait (Debug, Clone, PartialEq, etc.) because [T; 41]
does not implement them. Note that inability to use #[derive(Eq)]
means it can’t have the #[structural_match]
attribute in stable.
Since #[derive]
is just a procedural macro, we could actually inline the logic for [T; 41]
without waiting for type-level integers.
Design
“Inline” the derived method when a fixed-length array field [T; n]
or a tuple field (T, U, V)
is encountered, e.g. currently is expansion is like:
#[derive(Clone)]
pub struct X<T> {
a: ([T; 3], i32, T),
b: Vec<(T, T)>,
}
// =>
#[automatically_derived]
#[allow(unused_qualifications)]
impl <T: ::std::clone::Clone> ::std::clone::Clone for X<T> {
#[inline]
fn clone(&self) -> X<T> {
match *self {
X { a: ref __self_0_0, b: ref __self_0_1 } =>
X{a: ::std::clone::Clone::clone(&(*__self_0_0)),
b: ::std::clone::Clone::clone(&(*__self_0_1)),},
}
}
}
We will “inline” the clone
method so the expansion becomes:
X { a: ref __self_0_0, b: ref __self_0_1 } =>
X{
a: (
[
::std::clone::Clone::clone(&__self_0_0.0[0]),
::std::clone::Clone::clone(&__self_0_0.0[1]),
::std::clone::Clone::clone(&__self_0_0.0[2]),
],
::std::clone::Clone::clone(&__self_0_0.1),
::std::clone::Clone::clone(&__self_0_0.2),
),
b: ::std::clone::Clone::clone(__self_0_1),
},
Drawbacks
- The derive logic becomes more complicated: needs to recursively inspect the type of the field and generate different code according to the type.
- Special casing is not good.
Alternatives
- Fix RFC issue 1038 (Parameterize types over numerics / type level integers), so
[T; $N]
can actually implement all those traits. Note that fields with more than 12 tuple fields can still not be derived.
Unsolved questions
- Should we special case references e.g.
&&&&&&&[T; $N]
as well?