Strangeness in pattern matching mutable references in nested structs

There is a stackoverflow question that asks what the difference between matching with let Some(next) = &mut and let Some(ref mut next) = is.

I looked into binding modes and move/binding semantics of patterns but for life of my I can not figure out why one of these functions compiles but the other doesn't.

struct Node {
    next: Option<Box<Node>>,

fn node_matched<'a>(mut node: &'a mut Node)  {
    if let Some(next) = &mut {
        node = next;
    // here the compiler thinks is still borrowed = None;

fn node_reffed<'a>(mut node: &'a mut Node) {
    if let Some(ref mut next) = {
        node = next;
    // here the compiler thinks is not borrowed anymore = None;

I have been experimenting with different patterns and scenarios to figure this out and this only seems to happen with mutable references but I might be wrong.. Maybe its a bug maybe it is just some interested mechanism that isn't very well known but after spending quite some time trying to answer that stackoverflow question I really really itch to know what is going on.

1 Like

There's another bug report related to this, similar to the one linked in that StackOverflow thread but with a bit more discussion: if/while Some(n) = &mut foo sugar will leak a temporary mutable borrow to current scope in particular situation · Issue #62013 · rust-lang/rust · GitHub

I didn't follow all of the details, but I believe the difference in behavior here is unintentional and will be fixed eventually. When compiling with the next-generation borrow checker Polonius, both functions compile successfully.


Isn't the first example a mutable borrow of an Option, while the second is a mutable reference to a value inside an option? It kind of makes sense to me the compiler would think the first borrow was still alive.


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.