Duplicates of builtin derives with correct requirements
Currently, when you do:
#[derive(Clone)]
struct Foo<T>(std::sync::Arc<T>);
struct NoClone;
fn main() {
let foo = Foo(std::sync::Arc::new(NoClone));
let foo_ = foo.clone();
}
The code fails to compile. This is because the standard Clone and other derive macros that require fields to implement the trait they're deriving generate the following code: (they technically don't generate the code, but the functionality is equivalent)
impl<T> Clone for Foo<T> where
T: Clone,
Arc<T>: Clone,
{ ... }
Rather than:
impl<T> Clone for Foo<T> where
Arc<T>: Clone
/* and more, FieldT: Clone, for every field */
{ ... }
This is incorrect behaviour and makes the trait impls too narrow to be useful in many cases.
The reason for this behaviour is historical, and I don't believe it's possible to fix without a new edition, but that's far away and such a fix would break a lot of things.
It would be great if a temporary solution could be implemented in this crate to fix this, I can implement it myself if that's needed, but having this in an already widely used crate would be wonderful.
This is an intentional limitation of the standard derive macros intended for conservative protection from accidental breaking changes. Niko Matsakis' blog post calls it "perfect derive" and explains in detail why it's considered harmful.
The usual workaround is writing the trait impl manually, but I think just adding attribute config to allow the user configure where bounds on the impl is the better option. For example bon exposes syntax such as this:
#[derive(Trait(bounds(T: Clone, U: PartialEq)))]
That's really interesting, I hadn't considered that this could lead to semver hazards. Though I suppose it's up to @JelteF if derive_more can host "perfect" Debug/PartialEq/Clone/etc derives then, as it's still really useful to have in internal APIs
I found this crate, which does it perfectly: https://github.com/ModProg/derive-where
Nevermind, that enforces the type to implement the derived traits for all variations of the type arguments, rather than just adding requirements to the impl. So the issue is still up.
@Veetaha
standard derive macros intended for conservative protection from accidental breaking changes
And still, there is the majority of cases where derives are used in user code, and no such concerns are meaningful.