Skip to content

Inserting a conditional break in working code causes strange borrowck error #91363

Open
@SNCPlay42

Description

@SNCPlay42

This code compiles successfully:

pub struct Node {
    left: Option<Box<Node>>,
}

pub fn remove_min(
    root: &mut Option<Box<Node>>,
) {
    let mut p = root;
    while p.as_ref().unwrap().left.is_some() {
        let q = p.as_mut().unwrap();
        p = &mut q.left;
    }
    p.take();
}

I tried this version:

pub struct Node {
    left: Option<Box<Node>>,
}

pub fn remove_min(
    root: &mut Option<Box<Node>>,
) {
    let mut p = root;
    while p.as_ref().unwrap().left.is_some() {
        let q = p.as_mut().unwrap();
        if true { // or any arbitrary expression
            break;
        }
        p = &mut q.left;
    }
    p.take();
}

I expected this to compile successfully.

Instead, this happened:

error[E0499]: cannot borrow `*p` as mutable more than once at a time
  --> <source>:16:5
   |
10 |         let q = p.as_mut().unwrap();
   |                 - first mutable borrow occurs here
...
16 |     p.take();
   |     ^
   |     |
   |     second mutable borrow occurs here
   |     first borrow later used here

error: aborting due to previous error

Meta

Occurs on stable (1.56) on the playground.

Notably, this compiles succesfully with polonius.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-borrow-checkerArea: The borrow checkerA-control-flowArea: Control flowC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions