In the compiler error discussed at the end of the Transferring ownership section of this chapter, we see that the compiler noted that the data value is moved because it does not implement the Copy trait, which is interesting. What does that mean?
For some data types, particularly the primitive types such as integers and floating-point numbers, copying the bytes that represent them on the stack is all that is required to actually make a complete working copy of the data value. In other words, their representation does not refer to anything stored elsewhere in memory or otherwise rely on ownership to keep everything correct.
Data types that do not rely on ownership at all are said to have the Copy trait. We'll see how to declare that our own data types have the Copy trait in Chapter 8, Important Standard Traits.
When a value's data type has the Copy trait, Rust doesn't move the value when it is transferred. The receiver still receives the value, but the old value remains valid. Instead of moving, the value has been copied. This function has almost exactly the same structure as the uncertain_ownership function, which refuses to compile:
pub fn copied_ownership(switch: bool) {
let local = 4.0;
if switch {
receive_ownership(Point2D {x: local, y: 4.0});
}
println!("x is {}", x);
}
The important difference here is that local contains a floating-point value and the floating-point data types have the Copy trait, which means that even though the value of local is placed inside of a Point2D structure, and that structure is then moved to the receive_ownership function's scope, local remains valid in the current scope. That's because the value of local wasn't moved into Point2D. It was copied.