Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 857
sdgfsdh Avatar asked Aug 06 '18 09:08

sdgfsdh


People also ask

What is the difference between clone and copy in Rust?

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.

How do traits work in Rust?

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 .

What is auto trait in Rust?

An auto trait is the new name for the terribly named1 opt-in, built-in trait (OIBIT).

Does string implement the copy trait?

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.


1 Answers

  • 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();
}
like image 171
Boiethios Avatar answered Oct 12 '22 13:10

Boiethios