# [derive(Clone)] Is Broken

https://news.ycombinator.com/rss Hits: 6
Summary

use std::sync::Arc; struct NoClone; #[derive(Clone)] struct WrapArc<T>(Arc<T>); fn main() { let foo = WrapArc(Arc::new(NoClone)); let foo_ = foo.clone(); } Do you think this code should compile? What about the following code: struct AlwaysEq<T>(T); impl<T> PartialEq for AlwaysEq<T> { fn eq(&self, _other: &Self) -> bool { true } } impl<T> Eq for AlwaysEq<T> {} struct NotEq; #[derive(PartialEq, Eq)] struct WrapAlwaysEq<T>(AlwaysEq<T>); fn assert_is_eq(_: impl Eq) {} fn main() { let x = WrapAlwaysEq(AlwaysEq(NotEq)); assert_is_eq(x); } The second example is a bit far fetched, but you probably answered yes. But neither do. Why not? The implementation of #[derive(Clone)] in the Rust compiler generates a Clone implementation with the following requirements on the derived type: All fields must be Clone. All generic parameters must be Clone. Can you spot the issue here? It's the latter requirement: we cannot just require all generic parameters to be Clone, as we cannot assume they are used in such a way that requires them to be cloned.^1 This applies to practically all builtin derive traits, such as Clone, PartialEq, Eq, or even Debug. What can we do to fix this? There are two solutions to this. Both require deleting that second requirement. The hard way We could create a Rust RFC, hopefully not bikeshed it to death, and get it stabilized in the next Rust edition as it is a breaking change.^2 This would take 4+ years to stabilize and be available to everyone. That sucks, but is the correct thing to do in the long-term. The quick way We can just write our own macro that generates the following code: #[derive(CustomClone)] struct WrapArc<T>(Arc<T>); impl<T> Clone for WrapArc<T> where Arc<T>: Clone, { } This does the job correctly. And it's not even hard to do. I know people who do this internally in their company codebases - it's not much code. So I've opened an issue about replicating the builtin derive traits in a less restrictive and thus correct way in the derive_more cra...

First seen: 2025-07-08 07:29

Last seen: 2025-07-08 12:30