Borrow checker woes


#1

I’m trying to iterate downwards into a recursive structure, and I’ve boiled down some code into the following questions…

with this struct definition:

struct Recursive{
    inner:  Vec<Recursive>
}

Why does using (2) instead of (1) below cause the borrow checker to fail? The only difference is the type annotation…

fn main() {
    let mut rec = Recursive{ inner: Vec::new() };
    let mut reference = &mut rec;
    
    loop{
        let temp = reference; // (1) this line works
        //let temp : &mut Recursive = reference // (2) this line doesn't
        reference = &mut temp.inner[0];
    }
}

And what is the meaning of this syntax? I can’t seem to find an explanation anywhere:

loop{
    //reference = &mut reference.inner[0]; //this doesn't compile
    reference = &mut {reference}.inner[0]; //this compiles
}

#2

This is indeed strange. Would be curious to know the reason as well.

This basically moves reference out of a temp scope, yielding a new (temp) value, and then takes a reference of that. I think it basically “resets” ownership of reference (it’s a &mut reference, which is affine) and allows assignment back to it within the loop. I have a strong suspicion that this is basically equivalent to your (1) version, except the temp is essentially anonymous (generated by compiler, at least semantically).


#3

I think this post by @bluss covers this case (among others).


#4

Thanks for the link. So the tl;dr is that it’s an issue of compiler deciding to reborrow (a mutable reference) vs moving it. It’s too bad this wart still exists.