I have an enum in Rust which has one value that takes a String
:
#[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?
Since String implements the Drop trait, your struct can not implement the Copy. If you are looking to be making copies of your struct, then you need Clone trait.
For this reason, String is Clone but not Copy . Clone is a supertrait of Copy , so everything which is Copy must also implement Clone . If a type is Copy then its Clone implementation only needs to return *self (see the example above).
Performs copy-assignment from source . a. clone_from(&b) is equivalent to a = b. clone() in functionality, but can be overridden to reuse the resources of a to avoid unnecessary allocations.
You can't implement Copy for Box , that would allow creation of multiple boxes referencing the same thing. The good news is that you don't need to in order to solve your problem.
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
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
.
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()), } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With