# [derive(Clone)] Is Broken
Core issue with #[derive(Clone)]
- Thread centers on the fact that
#[derive(Clone)]adds bounds likeT: Cloneon generic types, even when only the fields need to beClone. - Example:
struct Foo<T>(Arc<T>)is derive-failing today becauseT: Cloneis required, thoughArc<T>: Cloneneeds no such bound. - This also affects other derivable traits (
Debug,PartialEq, etc.), making derive less useful for many generic types and for phantom parameters.
Historical and type-system constraints
- Linked design notes explain the original choice: “perfect derive” (deriving from field requirements) used to be blocked by:
- Need to allow cyclic trait reasoning (like for auto traits
Send/Sync), which is hard to keep sound. - A semver hazard: derived bounds would silently change when private fields change (e.g., switching from
Rc<T>toTin a list type alters whenList<T>: Cloneholds).
- Need to allow cyclic trait reasoning (like for auto traits
- Some argue this is now mostly a policy/semver question, not a hard technical blocker.
Workarounds and proposed improvements
- Several crates implement “perfect derive” or allow explicit
where-like annotations on derive to override bounds, sometimes with escape hatches for cycles. - Suggestions:
- Allow explicit bound syntax inside derive (e.g.
#[derive(Clone(bounds(Arc<T>: Clone)))]). - Add attributes to exclude fields from auto-derives (
#[noderive(Clone)]style). - Keep derive simple in
stdand rely on crates for advanced behavior.
- Allow explicit bound syntax inside derive (e.g.
Developer experience and error messages
- Multiple commenters report being badly confused the first time they hit this, especially when all fields are obviously
Clonebut the type isn’t. - Current diagnostics tend to point at the inner type (“implement Clone for T”), often suggesting the wrong fix.
- There is a concrete request to improve the error message by explaining that derive inserted overly restrictive bounds and suggesting a manual impl as a fix.
Comparisons and broader language debates
- Haskell’s deriving was cited; correction: Haskell effectively does “perfect derive” by constraining only field types.
- Long subthreads debate Rust vs Haskell features (strictness, linear/affine types) and Rust vs C++ complexity, macros, and ecosystem bloat.
- Some see Rust derive as a useful convenience whose edge cases don’t justify extra complexity; others see this quirk as an unnecessary “sharp edge” that undercuts Rust’s usual ergonomics.
LLMs and boilerplate
- One branch argues that LLMs can generate and maintain manual impls, reducing the need for richer derive mechanisms.
- Others are skeptical, pointing to hallucinations, overconfident wrong answers, and the risk of developers not recognizing subtle mistakes.