How do I implement Copy and Clone for a type that

2019-01-23 16:49发布

I have an enum in Rust which has one value that takes a String. This can be demonstrated with this simple example:

#[derive(Clone, Copy)]
enum Simple {
    Error(String),
    Okay,
    Foo([u32; 5]),
}

fn main() {
    let x = Simple::Error(String::from("blah"));
    let y = x.clone();
}

The enum value Foo above represents about 10 other enums I use that take copyable types or arrays of them. The compiler doesn't seem to complain about them, only the Error(String) which causes this:

error[E0204]: the trait `Copy` may not be implemented for this type
 --> src/main.rs:1:17
  |
1 | #[derive(Clone, Copy)]
  |                 ^^^^
2 | enum Simple {
3 |     Error(String),
  |           ------ this field does not implement `Copy`

For some reason, String is not copyable. I don't get this. How do I implement Clone for an enum for just the one type which has a problem while using the default impl for the rest?

标签: rust
2条回答
迷人小祖宗
2楼-- · 2019-01-23 17:06

Copy

Copy designates types for which making a bitwise copy creates a valid instance without invalidating the original instance.

This isn't true for String, because String contains a pointer to the string data on the heap and assumes it has unique ownership of that data. When you drop a String, it deallocates the data on the heap. If you had made a bitwise copy of a String, then both instances would try to deallocate the same memory block, which is undefined behaviour.

Since String doesn't implement Copy, your enum cannot implement Copy either because the compiler enforces that Copy types are composed only of Copy data members.

Clone

Clone merely provides a standard clone method, and it's up to each implementor to decide how to implement it. String does implement Clone, so you can put #[derive(Clone)] on your enum.

查看更多
祖国的老花朵
3楼-- · 2019-01-23 17:20

I did some exploring to see what a manual implementation would look like for an enum. I came up with this, but keep in mind you can also do #[derive(Clone)] as stated elsewhere and the compiler will do this for you.

enum Simple {
    Error(String),
    Okay,
    Foo([u32; 5]),
}

impl Clone for Simple {
    fn clone(&self) -> Simple {
        match self {
            Error(a) => Error(a.to_string()),
            Okay => Okay,
            Foo(a) => Foo(a.clone()),
        }
    }
}
查看更多
登录 后发表回答