'How do I implement Copy and Clone for a type that contains a String (or any type that doesn't implement Copy)?
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?
Solution 1:[1]
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()),
}
}
}
Solution 2:[2]
I found a solution using format.
Here, in this example trait Details is implemented for Car struct.
/*
Car example
- implement a trait `Detail` for different car objects (defined in `struct`)
NOTE: here, the `String` type creates a problem in return
*/
pub trait Detail {
fn brand(&self) -> String;
fn color(&self) -> String;
fn driving_mode(&self) -> bool;
fn manu_year(&self) -> u16;
}
// NOTE: Even after using Clone in derive attribute, it throws the same error
#[derive(Debug)] // used for printing via `println!`
struct Car {
brand: String,
color: String,
mode: bool, // manual: false, automatic: true
year: u16
}
impl Detail for Car {
fn brand(&self) -> String {
// using `format` instead of directly returning the brand bcoz it throws error:
// "move occurs because `self.brand` has type `String`, which does not implement the `Copy` trait"
return format!("{}", self.brand);
// return self.brand; // throws Error
}
fn color(&self) -> String {
return format!("{}", self.color);
// return self.color; // throws Error
}
fn driving_mode(&self) -> bool {
return self.mode;
}
fn manu_year(&self) -> u16 {
return self.year;
}
}
fn main() {
let c1 = Car {
brand: "BMW".to_string(),
color: "Dark Blue".to_string(),
mode: true,
year: 2012
};
println!("Car c1: \n{:#?}", &c1); // print the whole car c1
println!("Car c1 brand: {}", &c1.brand()); // only print the c1's brand
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Shepmaster |
| Solution 2 | abhi3700 |
