#[derive(Clone)] places unnecessarily restrictive bounds on type parameter


#1

Consider the following code:

use std::rc::Rc;

#[derive(Clone)]
struct Foo<T>(Rc<T>);

fn main() {}

I expect #[derive(Clone)] to generate an impl that looks like this:

impl<T> Clone for Foo<T> { /* ... */ }

Manually writing the impl this way works. However, #[derive(Clone)] appears to instead generate an impl that places overly restrictive bounds on T:

impl<T: Clone> Clone for Foo<T> { /* ... */ }

The Clone bound on T is not necessary because Rc<T>: Clone regardless of T.

Is this intended behavior or a bug?


#2

Rc doesn’t copy the internal data when cloned.

(it just copies a pointer an. increments the count)


#3

A very old “bug” (not really intended behaviour, but not really a bug either, more an implementation limitation as I understand it)


#4

It takes a while to really digest why derive bounds are hard just from the issue, so I’d also cite


#5

I’m not sure I completely understand what it is that makes this problem so difficult. My first thought is that it could be done simply by looking at what circumstances are required for each of a struct’s fields to be Clone (if it’s a type parameter, then require T: Clone; if it’s some other type, then look at the impls), and then merge those bounds.

What’s the problem with this approach?


#6

That’s exactly what the post I linked above explains: Recursive types break that naive algorithm, and if you want to figure out how to support recursive types, math jargon shows up.