Simple enum derives Debug and Clone take long time to compile

#[derive(PartialEq, Eq, Hash, Debug, Clone)]
pub enum Enum1 {
    Item1,
    Item2,
    Item3,
    // 20,000 more
}

The cargo expand shows that the Debug and Clone traits is expanded to large match with 20000 arms

// Debug
match (&*self,) {
    (&Enum1::Item1,) => {
        let debug_trait_builder =
            &mut ::core::fmt::Formatter::debug_tuple(f, "Item1");
        ::core::fmt::DebugTuple::finish(debug_trait_builder)
    }
    // 20,000 more
}
// Clone
match (&*self,) {
    (&Enum1::Item1,) => Enum1::Item1,
    // 20,000 more
}

The cargo rustc self profile shows the bottleneck:
type_check_crate > item_bodies_checking > typeck_item_bodies > typeck 18.2% of the time
match_checking > misc_checking_2 > check_match 29.5% of the time each * 2 times
MIR_borrow_checking > mir_borrowck 17% of the time

I want to improve the speed of compilation.
For the Debug trait, I'm planning to use a lazy_static hashmap to map the variants to string. Hopefully it's not a big problem.
For the Clone trait, since all the variants hold no data inside, I want to use a bitwise Copy, but Copy requires Clone to be implemented. Is there some way I can do a simple copy here?

Ways that I haven't tried yet:
num_traits::FromPrimitives & ToPrimitives
#[repr(u16)]

Any suggestion appreciates!

Implement Clone as just

impl Clone for Enum1 {
    fn clone(&self) -> Self { *self }
}

And you can implement PartialEq by delegating to (*a as usize).eq(&(*b as usize)) to also save a bunch of compilation time.

2 Likes

Great thanks!

For the PartialEq, the default generated implementation is comparing the discriminant_value, which is fine here. Some code looks redundant, but it should be easy for the compiler to optimize it without much time.

impl ::core::cmp::PartialEq for Enum1 {
    #[inline]
    fn eq(&self, other: &Enum1) -> bool {
        {
            let __self_vi = ::core::intrinsics::discriminant_value(&*self);
            let __arg_1_vi = ::core::intrinsics::discriminant_value(&*other);
            if true && __self_vi == __arg_1_vi {
                match (&*self, &*other) {
                    _ => true,
                }
            } else {
                false
            }
        }
    }
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.