Reputation: 1727
I'm trying to get a reference to the tail of a linked list, and here's the code I wrote:
pub struct ListNode {
pub next: Option<Box<ListNode>>,
}
fn tail(mut head: &mut Option<Box<ListNode>>) -> &mut Option<Box<ListNode>> {
while let Some(x) = head.as_mut() {
head = &mut x.next;
}
head
}
This fails to compile because it thinks I'm borrowing head as mutable twice. I was able to get to compile by changing it to this:
fn tail(mut head: &mut Option<Box<ListNode>>) -> &mut Option<Box<ListNode>> {
while head.is_some() {
head = &mut head.as_mut().unwrap().next;
}
head
}
It appears to me that these two functions do the exact same thing, but the first one looks a lot cleaner. Why doesn't it compile? Is there a better way of doing this than what I changed it to?
Upvotes: 2
Views: 66
Reputation: 70257
You already have a value of the correct reference type, so the as_mut
is unnecessary.
while let Some(x) = head {
head = &mut x.next;
}
head
I can't speak to why your first example doesn't compile, as I'm still no expert in speaking "borrow checker" myself, but my guess is that Rust is just being conservative and assuming that the head.as_mut()
borrow lasts into the variable x
, which gets put into head
, and therefore is a mutable borrow lasting as long as head
does, whereas when we directly access it as I do above, Rust is smart enough to understand what's really happening.
Upvotes: 1