Type does not implement the Copy Trait

Please, How can I implement the Copy Trait on the EdDsaSecretKey type?

#[derive(Debug, Clone, Eq)]
struct EdDsaExtendedPrivKey {
    pub private_key: EdDsaSecretKey,
    pub chain_code: ChainCode,
}

impl PartialEq for EdDsaExtendedPrivKey {
    fn eq(&self, other: &Self) -> bool {
        self.private_key == other.private_key && self.chain_code == other.chain_code
    }
}

#[derive(Debug)]
struct EdDsaSecretKey(ed25519_dalek::SecretKey);

impl Eq for EdDsaSecretKey {}

impl PartialEq for EdDsaSecretKey {
    fn eq(&self, other: &Self) -> bool {
        self.0.as_bytes() == other.0.as_bytes()
    }
}

impl Clone for EdDsaSecretKey {
    fn clone(&self) -> Self {
        *self <- here
    }
}
error[E0507]: cannot move out of `*self` which is behind a shared reference
   --> src/extended_key.rs:193:9
    |
193 |         *self
    |         ^^^^^ move occurs because `*self` has type `EdDsaSecretKey`, which does not implement the `Copy` trait

For more information about this error, try `rustc --explain E0507`.
error: could not compile `hdwallet_rs` due to previous error

You don't implement the Clone trait manually, normally. You simply derive it. In your case you have #[derive(Debug)] for EdDsaSecretKey - replace it with #[derive(Debug, Clone)].

Also, you cannot make a type Copy per-se - a struct can be Copy only when all its members are Copy. In your case, you don't need it also as far as I can tell.

1 Like

I'm using the Clone trait manually because the ed25519_dalek::SecretKey type does not implement the Clone trait, which then causes this conflicting error.

180 | #[derive(Debug, Clone)]
    |                 ----- in this derive macro expansion
181 | struct EdDsaSecretKey(ed25519_dalek::SecretKey);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `ed25519_dalek::SecretKey`
    |
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)

If you have control over the SecretKey struct (ie, you have written the code for it, its not a external library), then you have to derive Clone for that.

Alternatively, you have two choices:

  • File a bug-report with the author of the crate for this fix
  • Fork the project, make the changes and use that

Unfortunately, that's all you can do - you cannot forcibly implement a trait for a type that is not in your current crate.

1 Like

I didn't think of that, Thank you.

Somehow I think that the un-Cloneability of something called "SecretKey" may be a feature rather than a bug…

8 Likes

Interesting, What makes you think that?

Well, it's kind of obvious. A secret must not have more than 1 owner – if it's shared, it's not a secret any more. (And even "shared secrets" like RSA keys aren't usually shared in the plain just like that, they are encrypted and then re-created at the other side that needs to know them). So, trying to clone a credential is most likely a mistake or at least bad design, and it also increases the probability of an attacker being able to sniff it through side channel attacks or memory corruption.


As for your question, "doesn't implement Copy" is an error that isn't generally solved by trying to add Copy. As noted by others, Copy is not something that you can add after the fact; there are hard requirements on its implementation. The "doesn't implement Copy" thus isn't the interesting or relevant part of this error message – the essential is that you are trying to move something out of a reference, but that is generally not allowed. In the vast majority of cases, this means that you should access the specified value by reference only, instead of trying to take ownership of it. (Or, in your specific case, you should simply omit the Clone and Copy impls from your wrapper type, since it contains a credential.)

5 Likes

That makes sense, Thank you @H2CO3

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.