3
struct Foo(Option<Box<Foo>>);

fn func(mut foo: Foo) {
    let mut bar = &mut foo;
    loop {
        // while let Some(next) = bar.0.as_mut() {  // version-1
        // while let Some(next) = &mut bar.0 {  // version-2
        while let Some(ref mut next) = bar.0 {  // version-3
            bar = next.as_mut();
        }
    }
}

Rust Playground

In the above code, only version-3 can be compiled successfully. I would like to know the differences between these three versions and why only version-3 is valid.

Note that in version-3, bar.0 doesn't seem to move to the left pattern. One simple trial:

let mut a = Foo(Some(Box::new(Foo(None))));
if let Some(ref mut _b) = a.0 {
    // Foo does not implement the `Copy` trait
    println!("Go into if-let");
}
let b = a;  // Moving occurs here, so `a.0` is not moved

Error message of version-1:

error[E0499]: cannot borrow `bar.0` as mutable more than once at a time
 --> src/lib.rs:6:32
  |
6 |         while let Some(next) = bar.0.as_mut() {  // version-1
  |                                ^^^^^ mutable borrow starts here in previous iteration of loop

Error message of version-2:

error[E0499]: cannot borrow `bar.0` as mutable more than once at a time
 --> src/lib.rs:7:32
  |
7 |         while let Some(next) = &mut bar.0 {  // version-2
  |                                ^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
QuarticCat
  • 1,314
  • 6
  • 20

0 Answers0