Why does Rust not allow the copy and drop traits on one type?

  • A+
Category:Languages

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 the Drop trait. If the type needs something special to happen when the value goes out of scope and we add the Copy 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?

 


  • The Drop trait is used in an RAII context, typically when some resource needs to be released/closed when the object is destroyed.
  • In the other hand, a 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(); } 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: