0

I'm confused about how Rust decides when to move a mutable reference when passing it to a function. Consider the following code:

fn my_drop<T>(_x: T) {}

fn main() {
    let mut a = 1i32;
    let rm: &mut i32 = &mut a;
    my_drop(rm);
    let value = *rm;
    println!("{}", value);
}

As I expect, it fails to compile, because calling my_drop moves the value out of rm into the function parameter (according to the docs, this is exactly how drop is implemented). Since the type of rm is &mut i32, I expect that T is &mut i32, and that substituting that in should give exactly the same behaviour:

fn my_drop2(_x: &mut i32) {}

fn main() {
    let mut a = 1;
    let rm: &mut i32 = &mut a;
    my_drop2(rm);
    let value = *rm;
    println!("{}", value);
}

But for some reason this compiles (and runs) without complaint. Why is rm not moved out of when using my_drop2? And how is it being passed to my_drop2 without moving out of rm and without making a second mutable reference?

Bruce Merry
  • 751
  • 3
  • 11
  • TL;DR: Assigning a reference to another reference is handled specially by the compiler; it "reborrows" as though you'd written `my_drop2(&mut *rm);` but this only happens when the variable being assigned to (a function parameter in this case) is declared to be a reference type. In the generic type it is not explicitly declared to be a reference (it's `T`, not `&mut T`), so no reborrow happens. – cdhowie Jul 18 '22 at 21:24
  • Thanks. The links from the prior question seem to explain most of it. It's a pity it's not explained in the Reference. – Bruce Merry Jul 20 '22 at 06:11

0 Answers0