3 ms·
> In Rust, moves are destructive (which simplifies implementions - you don't need an "empty" state) and always bitwise (which is usually fine, so long as they'r
by est31 4y ago
> In Rust, moves are destructive (which simplifies implementions - you don't need an "empty" state) and always bitwise (which is usually fine, so long as they're destructive); and copies are always explicit so you don't have the above problem.
Rust has implicit copies too, e.g. if you do:
let v = 2u16;
foo(v);
then v is being copied. What Rust does not have is implicit deep copies. The auto-copying depends on the type and is only done for types that don't have a custom destructor, or to be more precise, implement the Copy trait. So a big array of integers gets copied (because it implements the Copy trait), but a Vec gets moved (because of its custom destructor there is no Copy trait implementation).
- mleonhard 4y agoIn Rust, types implement the Copy trait and the Drop (destructor) trait independently. Vec could easily implement Copy. It doesn't because copying a Vec requires an expensive heap allocation, which can surprise users when it happens implicitly.
- est31 4y agoNo you can't, there is a specific error for that. You can try it: struct Foo; impl Copy for Foo {} impl Drop for Foo { fn drop(&mut self) { // ... } } It gives the error: error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor --> src/main.rs:3:1 | 3 | impl Copy for Foo {} | ^^^^^^^^^^^^^^^^^^^^ `Copy` not allowed on types with destructors See also the "When can't my type be Copy?" section of the Rust documentation: https://doc.rust-lang.org/1.62.0/std/marker/trait.Copy.html#when-cant-my-type-be-copy https://doc.rust-lang.org/1.62.0/std/marker/trait.Copy.html#...
- quietbritishjim 4y agoSure, I knew about the Value trait but I thought it wasn't relevant for the general point (and I thought that sentence had too many parenthesised clarifications already!).
- tialaramex 4y agoAs Rust's documentation explains "... Under the hood, both a copy and a move can result in bits being copied in memory, although this is sometimes optimized away" What's important about Copy is that, since you said you want to permit Copy here, it's OK if Rust keeps both identical bit patterns alive after the bits are copied. Just keeping both alive is obviously better for trivial types like u32, but on modern hardware it's also true for somewhat more complicated types like &str (which is a pointer and a count) or SocketAddrV6 (an IPv6 address, a port number, flow label and so on). Thus, in your example, v is being bit copied (at least notionally) in both cases to become the parameter of this foo function, but because v is Copy, we can nevertheless use v again on the next line, the bits in v are still alive. If v was not Copy (e.g. an owned String) then foo(v) consumes v, it's moved into foo and now it's gone, we can't access v on the next line. The fact that foo(v) consumes v, is why core::mem::drop() is so trivial: https://doc.rust-lang.org/core/mem/fn.drop.html https://doc.rust-lang.org/core/mem/fn.drop.html