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

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
10
down vote

favorite












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?







share|improve this question





















  • This is kinda-sorta a formalization of what C++ calls the "Rule of Three".
    – trentcl
    Aug 7 at 14:34














up vote
10
down vote

favorite












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?







share|improve this question





















  • This is kinda-sorta a formalization of what C++ calls the "Rule of Three".
    – trentcl
    Aug 7 at 14:34












up vote
10
down vote

favorite









up vote
10
down vote

favorite











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?







share|improve this question













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?









share|improve this question












share|improve this question




share|improve this question








edited Aug 6 at 9:21









Boiethios

7,86622460




7,86622460









asked Aug 6 at 9:05









sdgfsdh

6,82863375




6,82863375











  • This is kinda-sorta a formalization of what C++ calls the "Rule of Three".
    – trentcl
    Aug 7 at 14:34
















  • This is kinda-sorta a formalization of what C++ calls the "Rule of Three".
    – trentcl
    Aug 7 at 14:34















This is kinda-sorta a formalization of what C++ calls the "Rule of Three".
– trentcl
Aug 7 at 14:34




This is kinda-sorta a formalization of what C++ calls the "Rule of Three".
– trentcl
Aug 7 at 14:34












2 Answers
2






active

oldest

votes

















up vote
15
down vote



accepted










  • 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();






share|improve this answer























  • "With those two descriptions, it is clearer that they are exclusive" what about an implementation of a shared pointer?
    – sdgfsdh
    Aug 6 at 11:58






  • 1




    @sdgfsdh When you copy a shared pointer, you have to increment the inner reference counter. That's not a simple memcpy. See the drop implementation of Rc for example.
    – Boiethios
    Aug 6 at 12:16










  • So Rust does not allow custom implementations of Copy?
    – sdgfsdh
    Aug 6 at 12:34






  • 2




    @sdgfsdh Nope. Let me add more information about this in my answer.
    – Boiethios
    Aug 6 at 12:37






  • 6




    @sdgfsdh actually rust allows something like a custom implementation of Copy. It is called Clone. Clone is always explizit, can perform additional operations (such as increasing a reference count), and can coexist with Drop.
    – kazemakase
    Aug 6 at 13:01


















up vote
4
down vote













Quoting the documentation.




[...] [A]ny type implementing Drop can't be Copy, because it's managing some resource besides its own size_of::<T> bytes.







share|improve this answer





















    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51704063%2fwhy-does-rust-not-allow-the-copy-and-drop-traits-on-one-type%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    15
    down vote



    accepted










    • 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();






    share|improve this answer























    • "With those two descriptions, it is clearer that they are exclusive" what about an implementation of a shared pointer?
      – sdgfsdh
      Aug 6 at 11:58






    • 1




      @sdgfsdh When you copy a shared pointer, you have to increment the inner reference counter. That's not a simple memcpy. See the drop implementation of Rc for example.
      – Boiethios
      Aug 6 at 12:16










    • So Rust does not allow custom implementations of Copy?
      – sdgfsdh
      Aug 6 at 12:34






    • 2




      @sdgfsdh Nope. Let me add more information about this in my answer.
      – Boiethios
      Aug 6 at 12:37






    • 6




      @sdgfsdh actually rust allows something like a custom implementation of Copy. It is called Clone. Clone is always explizit, can perform additional operations (such as increasing a reference count), and can coexist with Drop.
      – kazemakase
      Aug 6 at 13:01















    up vote
    15
    down vote



    accepted










    • 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();






    share|improve this answer























    • "With those two descriptions, it is clearer that they are exclusive" what about an implementation of a shared pointer?
      – sdgfsdh
      Aug 6 at 11:58






    • 1




      @sdgfsdh When you copy a shared pointer, you have to increment the inner reference counter. That's not a simple memcpy. See the drop implementation of Rc for example.
      – Boiethios
      Aug 6 at 12:16










    • So Rust does not allow custom implementations of Copy?
      – sdgfsdh
      Aug 6 at 12:34






    • 2




      @sdgfsdh Nope. Let me add more information about this in my answer.
      – Boiethios
      Aug 6 at 12:37






    • 6




      @sdgfsdh actually rust allows something like a custom implementation of Copy. It is called Clone. Clone is always explizit, can perform additional operations (such as increasing a reference count), and can coexist with Drop.
      – kazemakase
      Aug 6 at 13:01













    up vote
    15
    down vote



    accepted







    up vote
    15
    down vote



    accepted






    • 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();






    share|improve this answer















    • 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();







    share|improve this answer















    share|improve this answer



    share|improve this answer








    edited Aug 6 at 12:47


























    answered Aug 6 at 9:14









    Boiethios

    7,86622460




    7,86622460











    • "With those two descriptions, it is clearer that they are exclusive" what about an implementation of a shared pointer?
      – sdgfsdh
      Aug 6 at 11:58






    • 1




      @sdgfsdh When you copy a shared pointer, you have to increment the inner reference counter. That's not a simple memcpy. See the drop implementation of Rc for example.
      – Boiethios
      Aug 6 at 12:16










    • So Rust does not allow custom implementations of Copy?
      – sdgfsdh
      Aug 6 at 12:34






    • 2




      @sdgfsdh Nope. Let me add more information about this in my answer.
      – Boiethios
      Aug 6 at 12:37






    • 6




      @sdgfsdh actually rust allows something like a custom implementation of Copy. It is called Clone. Clone is always explizit, can perform additional operations (such as increasing a reference count), and can coexist with Drop.
      – kazemakase
      Aug 6 at 13:01

















    • "With those two descriptions, it is clearer that they are exclusive" what about an implementation of a shared pointer?
      – sdgfsdh
      Aug 6 at 11:58






    • 1




      @sdgfsdh When you copy a shared pointer, you have to increment the inner reference counter. That's not a simple memcpy. See the drop implementation of Rc for example.
      – Boiethios
      Aug 6 at 12:16










    • So Rust does not allow custom implementations of Copy?
      – sdgfsdh
      Aug 6 at 12:34






    • 2




      @sdgfsdh Nope. Let me add more information about this in my answer.
      – Boiethios
      Aug 6 at 12:37






    • 6




      @sdgfsdh actually rust allows something like a custom implementation of Copy. It is called Clone. Clone is always explizit, can perform additional operations (such as increasing a reference count), and can coexist with Drop.
      – kazemakase
      Aug 6 at 13:01
















    "With those two descriptions, it is clearer that they are exclusive" what about an implementation of a shared pointer?
    – sdgfsdh
    Aug 6 at 11:58




    "With those two descriptions, it is clearer that they are exclusive" what about an implementation of a shared pointer?
    – sdgfsdh
    Aug 6 at 11:58




    1




    1




    @sdgfsdh When you copy a shared pointer, you have to increment the inner reference counter. That's not a simple memcpy. See the drop implementation of Rc for example.
    – Boiethios
    Aug 6 at 12:16




    @sdgfsdh When you copy a shared pointer, you have to increment the inner reference counter. That's not a simple memcpy. See the drop implementation of Rc for example.
    – Boiethios
    Aug 6 at 12:16












    So Rust does not allow custom implementations of Copy?
    – sdgfsdh
    Aug 6 at 12:34




    So Rust does not allow custom implementations of Copy?
    – sdgfsdh
    Aug 6 at 12:34




    2




    2




    @sdgfsdh Nope. Let me add more information about this in my answer.
    – Boiethios
    Aug 6 at 12:37




    @sdgfsdh Nope. Let me add more information about this in my answer.
    – Boiethios
    Aug 6 at 12:37




    6




    6




    @sdgfsdh actually rust allows something like a custom implementation of Copy. It is called Clone. Clone is always explizit, can perform additional operations (such as increasing a reference count), and can coexist with Drop.
    – kazemakase
    Aug 6 at 13:01





    @sdgfsdh actually rust allows something like a custom implementation of Copy. It is called Clone. Clone is always explizit, can perform additional operations (such as increasing a reference count), and can coexist with Drop.
    – kazemakase
    Aug 6 at 13:01













    up vote
    4
    down vote













    Quoting the documentation.




    [...] [A]ny type implementing Drop can't be Copy, because it's managing some resource besides its own size_of::<T> bytes.







    share|improve this answer

























      up vote
      4
      down vote













      Quoting the documentation.




      [...] [A]ny type implementing Drop can't be Copy, because it's managing some resource besides its own size_of::<T> bytes.







      share|improve this answer























        up vote
        4
        down vote










        up vote
        4
        down vote









        Quoting the documentation.




        [...] [A]ny type implementing Drop can't be Copy, because it's managing some resource besides its own size_of::<T> bytes.







        share|improve this answer













        Quoting the documentation.




        [...] [A]ny type implementing Drop can't be Copy, because it's managing some resource besides its own size_of::<T> bytes.








        share|improve this answer













        share|improve this answer



        share|improve this answer











        answered Aug 6 at 9:16









        hellow

        2,1581333




        2,1581333






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51704063%2fwhy-does-rust-not-allow-the-copy-and-drop-traits-on-one-type%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            What is the equation of a 3D cone with generalised tilt?

            Color the edges and diagonals of a regular polygon

            Relationship between determinant of matrix and determinant of adjoint?