Hello,
why does Rust display an error message for Test1 below, but not for Test2. They both contain inner structs which are Clone, one which derives Clone and one which implements it manually.
I would like to know how Rust derives Clone in a way that causes the error message below, I thought the manual implementation of Outer2 is essentially equivalent to the derived Clone. But it apparently isn't.
use std::sync::Arc;
struct Value;
#[derive(Clone)]
struct Test1(Outer1<Value>);
// ^^^^^^^^^^^^^
// The trait bound `Value: std::clone::Clone` is not satisfied.
#[derive(Clone)]
struct Test2(Outer2<Value>);
#[derive(Clone)]
struct Outer1<T>(Arc<T>);
struct Outer2<T>(Arc<T>);
impl<T> Clone for Outer2<T> {
fn clone(&self) -> Self {
Outer2(self.0.clone())
}
}
fn main() {}
Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `Value: std::clone::Clone` is not satisfied
--> src/main.rs:6:14
|
6 | struct Test1(Outer1<Value>);
| ^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `Value`
|
= note: required because of the requirements on the impl of `std::clone::Clone` for `Outer1<Value>`
= note: required by `std::clone::Clone::clone`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
error: Could not compile `playground`.
To learn more, run the command again with --verbose.
Because the Clone derive blindly bind T: Clone even though Arc<T>: Clone no matter what T is. You correctly don't do that. The Clone derive (and the others in std) is kinda hacky and works in the simple case, but in anything more than the simple case it falls over.
I think that it shouldn't touch the type parameter unless it needs to, and that the derive should works solely based on the fields, but it is too late to change that now.
It's like that way deliberately. Otherwise, you could change that Arc<T> to a T, and this seemingly internal implementation detail would change the public trait bounds in an impl you can't see.