Why can't this clone?

Here is a minimal failure case:


pub trait EnvBaseT {
    type Storage: Clone;
}

#[derive(Clone)]
pub struct Ten<Env: EnvBaseT> {
    pub storage: Env::Storage,
}

impl<Env: EnvBaseT> Ten<Env> {
    pub fn new() -> Ten<Env> {
        panic!()
    }
}


pub trait EnvT : EnvBaseT + Sized {
    fn foo(x: Ten<Self>) {
        let y = x.clone();
    }
}

Here is the error I get:

7  | pub struct Ten<Env: EnvBaseT> {
   | ----------------------------- method `clone` not found for this
...
20 |         let y = x.clone();
   |                   ^^^^^
   |
   = note: the method `clone` exists but the following trait bounds were not satisfied:
           `Ten<Self> : std::clone::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: `std::clone::Clone`

Here is why I think it should work:

EnvBaseT says that Storage supports Clone.

Then, on struct Ten, we say that Env satisfies trait EnvBaseT
Therefore, we should be able to clone "storage"
Then, we have #[derive(Clone)] which should auto derive Clone for the entire struct.

  1. Where is my logic wrong?

  2. How do we fix this?

Deriving Clone will require that Env generic type itself is Clone, which it isn’t (only its associated type is). So you can impl Clone manually for Ten here instead.

2 Likes

@vitalyd : That makes sense. Everything works now. Thanks!

This is related to issue #26925.