It feels like they easily could; they all can implement Copy, and it feels like a repr is as much a part of the public API as implementing Copy is, so removing the repr having the side effect of automatically un-implementing Copy sounds reasonable…
Are there places where it wouldn’t make sense for the compiler to auto-implement Copy for all enums with a primitive repr?
With this formulation, it is guarenteed that Empty::fill will only be called once or that the closure will panic. Using this information you can build some other apis on top of this. For example, a version of scoped threads or some form of the builder pattern.
None of this would be possible if you forced the compiler to auto-implement Copy.
I understand this in general, but I’m having trouble thinking of when this might apply to something which you’re specifically marking as being implemented as a primitive integer (which itself is Copy)…
But that is just one case, we can’t have the compiler special case only a few things or make Rust even more hard to learn. Also, how would Rust know when to implement Copy? Would it blindly try and implement Copy if it could? If so, then you would have to really think about every type and see if it should be Copy, because making it non-Copy would be a breaking change.
In my example, you could make Empty auto-impl Copy, and that would be a huge difference in semantics.
If the type is an enum, and has a repr attribute which shows that it has an explicit repr which is a primitive integer type, implement Copy.
Definitely nothing more general than that.
This doesn’t seem too crazy, because such an enum effectively is an integer (for which Copy is already implemented). Because of this, it also doesn’t feel like a particularly special case, if you view it through the lens of “an enum with repr(u8) is just a u8 with some sugar around it, and because u8 is Copy so is the enum”.
Oh, I see, that seems more reasonable. I think I misunderstood what you said earlier. I don’t think we can do this because it would be a breaking change.
A similar case like struct NewType(i32) also doesn’t implement Copy automatically, not even when it has #[repr(transparent)]. Supporting Copy has semantic meaning that must be explicitly opted into.
This suggestion seems reasonable, but it has huge learnability problem. Currently all types do not impls any trait by default, except for auto traits. But with this suggestion, it becomes: all types do not impls any trait by default, except for auto traits, or if the type is an enum, and has a repr attribute which shows that it has an explicit repr which is a primitive integer type, then it impls Copy. And everybody should remember this edge case, or they will face the “Why my enum impls Copy? Oh wait, this is the case when…” moment. Compare this with just adding #[derive(Clone, Copy)] line over such types. Will it worth it?
Anyway, it would be breaking change for all existing non-Copy such enum types.
Here is a potentially interesting trick: if you are afraid of forgetting to impl / derive Copy for a “trivial” case such as a simple enum (when there is no gigantic variant among them), you can enable the #![deny(missing_copy_implementations)] lint and then use #[allow(missing_copy_implementations)] as an “opt-out” Copy on the defined structs / enums that you may wish to “un-Copy” (there is also missing_debug_implementations, which I find extremely helpful)