Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy/move semantics documentation of &T/&mut T types itself

Tags:

rust

I'm looking for the document about copy/move semantics of reference and mutable reference types.

The following code snippet shows immutable references (& T) implement the Copy trait and mutable references (&mut T) do not.

struct T;
fn copyable<U>(_: U) where U: Copy {}

fn main() {
    let a = &T;
    copyable(a);  // OK

    let b = &mut T;
    copyable(b);
    // error: the trait `core::marker::Copy` is not implemented for the type `&mut T`
}

But I can't find the description of this behavior. Someone know some (un)official documents? (or am I wrong?)

like image 224
yohjp Avatar asked May 23 '16 00:05

yohjp


People also ask

What is copy semantics?

Value (or “copy”) semantics mean assignment copies the value, not just the pointer. C++ gives you the choice: use the assignment operator to copy the value (copy/value semantics), or use a pointer-copy to copy a pointer (reference semantics).

What is a move semantic?

Move semantics is a set of semantic rules and tools of the C++ language. It was designed to move objects, whose lifetime expires, instead of copying them. The data is transferred from one object to another. In most cases, the data transfer does not move this data physically in memory.

When should I use move semantics?

That's what rvalue references and move semantics are for! Move semantics allows you to avoid unnecessary copies when working with temporary objects that are about to evaporate, and whose resources can safely be taken from that temporary object and used by another.

When should we prefer move over copy semantics?

Overview. Move semantics are used to move resources from one object to another without copying. This is applicable when we try to pass an object to a function or when an object is being returned from a function.


2 Answers

Rust's std::marker::Copy trait reference says (thanks to @Chris Emerson):

When can my type not be Copy?
Some types can't be copied safely. For example, copying &mut T would create an aliased mutable reference, and copying String would result in two attempts to free the same buffer.
[...]

like image 126
yohjp Avatar answered Nov 07 '22 12:11

yohjp


As an addition to your code, you can always ask the compiler to tell you if a type can be copied, even without being able to construct that type:

fn is_this_type_copy<T: Copy>() {}

fn main() {
    is_this_type_copy::<&u8>();
}

If a type does not implement Copy, the compiler will produce an error.

You can extend this to ask the question for every reference to a type. Your existing code only shows that an immutable reference to a specific type implements Copy:

fn is_every_reference_copy<T>() {
    is_this_copy::<&T>()
}

Doing the same thing for &mut T:

fn is_every_mut_reference_copy<T>() {
    is_this_copy::<&mut T>()
}

Produces the same error you saw:

error[E0277]: the trait bound `&mut T: std::marker::Copy` is not satisfied
 --> src/main.rs:8:5
  |
8 |     is_this_copy::<&mut T>()
  |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&mut T`
  |
  = note: required by `is_this_copy`

We've already seen why &mut T cannot be copied, but why can &T be copied? In a way, that's kind of the entire point of a reference. A reference is a way of cheaply sharing data. Instead of needing to clone (potentially expensively) something to give to multiple things, we can simply give each thing a lightweight reference to the original thing. If references couldn't be copied, they wouldn't have nearly the same amount of value.

like image 22
Shepmaster Avatar answered Nov 07 '22 12:11

Shepmaster