Reborrow vs move


I was trying to understand and the subsequent comment. I simplified the code, which you can see below:


struct LinkedList {
    val: u64,
    next: Box<LinkedList>,

impl LinkedList {
    fn get_index(&mut self, idx: usize) -> u64 {
        let mut node = self;
        for i in 0..idx {
            node = &mut;

fn main() {}

There are a number of errors, but this is basically what it complains about:

<anon>:10:13: 10:34 error: cannot assign to `node` because it is borrowed [E0506]
<anon>:10             node = &mut;

arielb1 notes in the issue that you can fix this by changing &mut to &mut {node}.next and says this is about reborrow vs move, linking to Unfortunately I’m not finding that link very illuminating, so I figured I’d post here rather than polluting the issue.

In short: what additional information does block brackets around node give the compiler to allow this to work? I’m aware of the usage of blocks to restrict borrows, but I always see that with an expression or multiple statements rather than a single variable name - intuitively, I’d expect {x} to be the same as x. Any help much appreciated!

1 Like

Move semantics with references

You might like to read the blog post Stuff the Identity Function Does in Rust. I think this explanation makes this pattern a little bit more clear.

Basically, in Rust, there are a few places where you could either re-borrow or move a particular object. The default that the compiler chooses, of reborrowing, generally works out well. But in some cases, that default isn’t actually correct.

When you pass an object into a function or method by value, that moves it into the function, and if you return it it moves it out. A block acts similarly; if you return a value from a block by writing it as the last expression in the block, the value is moved out.

Now, in this case, node is an &mut LinkedList. The default when writing &mut is to reborrow node, so you can still use it later on once the reborrow ends. However, in this case, that causes a problem as you are trying to actually update node, but it’s reborrowed by the &mut expression. If you instead wrap node in a block, so the block is returning the value of node, it has to be moved out of instead of reborrowed; and that actually does what you want here, since you are actually just discarding the original reference to node when traversing to the next one.



That’s a strange way of using Rust’s features and also hacking around the limitation.
&mut {node} this blew my mind, didn’t think of this before that…
When I see { something_here } I instantly think of initialization(because of C++).

Interesting, because I would of thought of:

node = {

But because of C++, my mind blacks out on node = {node}, thinking of initialization.



I still don’t understand why even with {node} it works.
&mut self is a mutable reference. let mut node = selfshould also be a mutable reference(you don’t take ownership let mut node = *self)…
Should it not allow you to move out node?
I would expect {node} to throw an error saying that you cannot move it out because it is a reference, you are not the owner of the data. In my mind this moves out self, which I guess I got it wrong.



{node} is not moving the thing node points to, it’s moving the pointer itself. &mut T pointers are non-copyable, meaning they can only be moved or re-borrowed.

If Rust didn’t do automatic re-borrowing, then any time you did func(some_mut_borrow), then some_mut_borrow would be unusable after the function call. That would be a huge pain in the backside, so the compiler inserts the rough equivalent of func(&mut *some_mut_borrow) for you.


Idiomatic way for passing an optional, mutable reference around?

Thanks for the explanation.

This basically explains everything. It’s not = *node but = node.



Thanks to everyone for the explanations and links. I realise now that my problem was that I didn’t really understand reborrowing or why it’s used. I do now!

For future readers, reborrowing has some official documentation at

(apologies for bumping)

1 Like


I found that the identity function trick doesn’t always work:

fn bar(&mut i32) -> &mut i32;

fn foo(mut r: &mut i32) -> &mut i32 {
    for _ in 0 .. 10 {
        r = bar({ r }); // does not work

Instead I had to resort to using a dummy let

fn foo(mut r: &mut i32) -> &mut i32 {
    for _ in 0 .. 10 {
        r = bar({ let r = r; r });

It would be nice to have a blessed way to do this TBH (maybe create a macro for this?).



The good news is NLL fixes it without having to do any explicit moves at all:



For future readers, reborrowing has some official documentation at

Sorry for bumping, but the link went dead (archive) and this thread is easier to find than up-to-date documentation. I think the NLL RFC covers liveness and reborrowing now.

1 Like