+ 7

Problem with mutable references in Rust

I was trying to make a Linked list in rust. https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2c092e247e1c08b8f0dd802657f6b250 The `next` method on mutable iterator for my linked list (named ListIteratorMutable on line 143) has a return type `&'a mut Node<T>`. When I run the code, it gives me an error "cannot move out of `node` because it is borrowed". As far as I understood, it was because of more than 1 mutable references being made (because the immutable ListIterator on line 128 works fine). The weird part was that when I changed the return type from `&'a mut Node<T>` to `&'a mut T` and made the changes necessary to return that type, it worked fine. https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=a881ec2bfd259bae9c6bbdbb3cdbfb7b I would love an explanation on what just happened.

16th Jul 2020, 5:31 PM
XXX
XXX - avatar
3 odpowiedzi
+ 5
Let's look into the code step by step. ``` self.next = node.next.as_mut().map(|n| &mut **n); ``` In this line the type of "node" variable is `&'a mut Node<T>`, and that of `node.next.as_mut()` is `Option<&'b mut Box<Node<T>>>`, where 'b is the lifetime of mutable borrow of the 'node.next' field (which has also 'a lifetime). Now we use `map()`. The type of argument "n" is `&'b mut Box<Node<T>>`. The key point is that the Rust compiler resolves `&mut **n` expression as `DerefMut::deref_mut(n)` by auto-dereferencing rule (See https://stackoverflow.com/a/53344847 for details). Therefore the type of `&mut **n` is `&'b mut Node<T>`. That means, `&mut **n` borrows `node.next` variable. Be careful that "node" variable is a mutable reference. Unlike the "node" variable, which itself is a temporary variable and has also temporary lifetime, "node.text" field lives with 'a lifetime. Thus the following code is valid. ``` self.next = node.next.as_mut().map(|n| &mut **n); ``` However, if you return "node" variable, there would be two mutable borrows to "node.next" field: "self.next" and returned value. That's why rustc lifetime checker detects the first code is invalid. In the second code, you return a mutable reference to "node.value", which is not borrowed by any variable. Since rustc allows the simultaneous borrow of "node.value" and "node.text" fields, the second code is valid.
19th Jul 2020, 4:12 PM
Kogia-sima
Kogia-sima - avatar
+ 1
Okay!! So summed up, in code 1, I was making two mutable references but since one of them was temporary, everything was fine. But when I returned the temporary reference, there were two references with the same lifetime. In code 2, I was make mutable references of two different things so everything was fine. Am I right?? Anyways thanks for the explanation, I wasn't expecting an answer. Looks like no one knows rust in this platform.
19th Jul 2020, 4:29 PM
XXX
XXX - avatar
+ 1
Definitely you are right. I hope sololearn supports Rust programming language :)
19th Jul 2020, 4:48 PM
Kogia-sima
Kogia-sima - avatar