Search code examples
rustownership

Cannot understand why this code is working according to the rules of ownership


I have the following code

use euclid::Vector3D;

fn main() {
    fn add_vectors<Unit>(a: Vector3D::<f64, Unit>, b: Vector3D::<f64, Unit>) -> Vector3D::<f64, Unit> {
        // I take ownership of `a` and `b`.
        Vector3D::<f64,Unit>::new(a.x+b.x, a.y+b.y, a.z+b.z) // Explicitly create a new vector, and return it together with its ownership.
    } // `a` and `b` go out of scope, they are dropped.
    enum Meters {}
    let v1 = Vector3D::<f64,Meters>::new(1., 2., 3.);
    let v2 = Vector3D::<f64,Meters>::new(1., 2., 3.);
    // Up to here, `main` is the owner of `v1` and `v2`.
    println!("Added: {:?}", add_vectors(v1,v2)); // Ownership is transferred to `add_vectors`.
    println!("Original vectors: {:?} and {:?}", v1, v2); // `v1` and `v2` should have been dropped by now.
}

which compiles without warnings and runs, as you would expect in Python. However, this is Rust, and I don't understand how is that the second println! can use v1 and v2, given that according to my understanding from ownership (Rust book) this shouldn't be possible. Here is my reasoning:

  1. add_vectors receives the vectors themselves, not references. Hence, it takes ownership of them.
  2. In the body of add_vectors, a new Vector3D::<f64,Unit> is explicitly created and returned.
  3. When add_vectors reaches the end, a and b go out of scope, so they are dropped.
  4. Now v1 and v2 exist no longer.

(I am just learning Rust, sorry if the answer is too obvious and I don't see it.)


Solution

  • Most of euclid's types are Copy if the underlying T is Copy. This means that they don't get moved out of their original locations, just copied.