From the book:
Rust won’t let us annotate a type with the
Copy
trait if the type, or any of its parts, has implemented theDrop
trait. If the type needs something special to happen when the value goes out of scope and we add theCopy
annotation to that type, we’ll get a compile time error.
Why was the design decision made to disallow Copy
and Drop
on the same type?
Differs from Copy in that Copy is implicit and extremely inexpensive, while Clone is always explicit and may or may not be expensive. In order to enforce these characteristics, Rust does not allow you to reimplement Copy , but you may reimplement Clone and run arbitrary code.
A trait is a language feature that tells the Rust compiler about functionality a type must provide. As you can see, the trait block looks very similar to the impl block, but we don't define a body, only a type signature. When we impl a trait, we use impl Trait for Item , rather than only impl Item .
An auto trait is the new name for the terribly named1 opt-in, built-in trait (OIBIT).
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.
Drop
trait is used in an RAII context, typically when some resource needs to be released/closed when the object is destroyed.Copy
type is a trivial type that can be copied with a memcpy
only.With those two descriptions, it is clearer that they are exclusive: it makes no sense to memcpy
nontrivial data: what if we copy the data, and we drop one of the copies? The inner resource of the other copy will not be reliable anymore.
In fact, Copy
in not even a "real" trait, in that it does not define any function. It is a special marker that says to the compiler: "you can duplicate myself with a simple bytes copy". So you cannot provide a custom implementation of Copy
, because there is no implementation at all. However, you can mark a type as copyable:
impl Copy for Foo {}
or better, with a derive:
#[derive(Clone, Copy)]
struct Foo { /* ... */ }
This builds only if all the fields implement Copy
. Otherwise, the compiler refuses to compile because this is unsafe.
For the sake of an example, let's suppose that the File
struct implements Copy
. Of course, this is not the case, and this example is wrong and cannot compile:
fn drop_copy_type<T>(T x)
where
T: Copy + Drop,
{
// The inner file descriptor is closed there:
std::mem::drop(x);
}
fn main() {
let mut file = File::open("foo.txt").unwrap();
drop_copy_type(file);
let mut contents = String::new();
// Oops, this is unsafe!
// We try to read an already closed file descriptor:
file.read_to_string(&mut contents).unwrap();
}
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