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?
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
, becauseString
contains a pointer to the string data on the heap and assumes it has unique ownership of that data. When you drop aString
, it deallocates the data on the heap. If you had made a bitwise copy of aString
, then both instances would try to deallocate the same memory block, which is undefined behaviour.Since
String
doesn't implementCopy
, yourenum
cannot implementCopy
either because the compiler enforces thatCopy
types are composed only ofCopy
data members.Clone
Clone
merely provides a standardclone
method, and it's up to each implementor to decide how to implement it.String
does implementClone
, so you can put#[derive(Clone)]
on yourenum
.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.