trait Trait {
type Sub;
}
struct A;
#[derive(Clone)]
struct B;
impl Trait for A {
type Sub = B;
}
#[derive(Clone)]
struct C<T: Trait>(T::Sub);
fn main() {
let x = C::<A>(B);
x.clone();
}
Such compiler behavior reminds me of PhantomData: it "acts like" it own a T, which in this case it doesn't. Further tests show that even if Clone is implemented for A and compiled, A's clone is never called when calling clone on C.
BTW, can I use PhantomData for cases that don't really own a value of some type, such as a read handle which deserialize the output to some type? This is the case with mongodb's Collection, which uses PhantomData.
What gives you the impression that A needs to be cloned in your example? C never has an instance of A, and the trait doesn't provide a constructor of any kind, so how could it possibly call clone on A?
Yes, any time you need a type parameter but don't store a value of that type directly inside it PhatomData is the simplest solution.
It's not my impression, it's a compiler error. I forgot to paste it just now, sorry.
Compiling playground v0.0.1 (/playground)
error[E0599]: the method `clone` exists for struct `C<A>`, but its trait bounds were not satisfied
--> src/main.rs:19:7
|
5 | struct A;
| -------- doesn't satisfy `A: Clone`
...
15 | struct C<T: Trait>(T::Sub);
| ------------------
| |
| method `clone` not found for this struct
| doesn't satisfy `C<A>: Clone`
...
19 | x.clone();
| ^^^^^ method cannot be called on `C<A>` due to unsatisfied trait bounds
|
note: trait bound `A: Clone` was not satisfied
--> src/main.rs:14:10
|
14 | #[derive(Clone)]
| ^^^^^ unsatisfied trait bound introduced in this `derive` macro
= note: the following trait bounds were not satisfied:
`A: Clone`
which is required by `C<A>: Clone`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `clone`, perhaps you need to implement it:
candidate #1: `Clone`
help: consider annotating `A` with `#[derive(Clone)]`
|
5 | #[derive(Clone)]
|
For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground` due to previous error