Pre-RFC: Support deriving traits with long array/tuple fields


#1

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?

#2

Deriving for arrays will likely be solved by integer generics.

Tuples… well you probably shouldn’t be using 13-tuples or bigger.


#3

Has there been any headway on integer generics?


#4