Skip to content

Cannot return value from loop when temporary mutable access occurs before. #133539

Open
@nikvoid

Description

@nikvoid

I tried this code:

struct A {
    buf: [u8; 32],
}

struct Ref<'a> {
    slice: &'a [u8]
}

pub fn mkref(buf: &[u8]) -> Option<Ref> {
    Some(Ref {
        slice: &buf[1..8]
    })
}

impl A {
    // Borrowck error
    pub fn read<'a>(&'a mut self) -> Option<Ref<'a>> {
        loop {
            self.buf.rotate_left(4);

            match mkref(&self.buf) {
                Some(rf) => return Some(rf),
                None => continue,
            }

        }

        None
    }

    // Borrowck error
    pub fn read_break<'a>(&'a mut self) -> Option<Ref<'a>> {
        let r = loop {
            self.buf.rotate_left(4);

            match mkref(&self.buf) {
                Some(rf) => break Some(rf),
                None => continue,
            }
        };

        r
    }

    // OK
    pub fn read_inline<'a>(&'a mut self) -> Option<Ref<'a>> {
        loop {
            self.buf.rotate_left(4);

            return Some(Ref { slice: &self.buf[..] });
        }

        None
    }

    // OK
    pub fn read_noloop<'a>(&'a mut self) -> Option<Ref<'a>> {
        self.buf.rotate_left(4);

        match mkref(&self.buf) {
            Some(rf) => return Some(rf),
            None => return None,
        }
    }
}

I expected to see this happen: No errors

Instead, this happened: Cannot return value from loop when temporary mutable access occurs before.

error[E0502]: cannot borrow `self.buf` as mutable because it is also borrowed as immutable
  --> src/lib.rs:23:13
   |
21 |     pub fn read<'a>(&'a mut self) -> Option<Ref<'a>> {
   |                 -- lifetime `'a` defined here
22 |         loop {
23 |             self.buf.rotate_left(4);
   |             ^^^^^^^^ mutable borrow occurs here
24 |
25 |             match mkref(&self.buf) {
   |                         --------- immutable borrow occurs here
26 |                 Some(rf) => return Some(rf),
   |                                    -------- returning this value requires that `self.buf` is borrowed for `'a`

error[E0502]: cannot borrow `self.buf` as mutable because it is also borrowed as immutable
  --> src/lib.rs:38:13
   |
36 |     pub fn read_break<'a>(&'a mut self) -> Option<Ref<'a>> {
   |                       -- lifetime `'a` defined here
37 |         let r = loop {
38 |             self.buf.rotate_left(4);
   |             ^^^^^^^^ mutable borrow occurs here
39 |
40 |             match mkref(&self.buf) {
   |                         --------- immutable borrow occurs here
...
46 |         r
   |         - returning this value requires that `self.buf` is borrowed for `'a`

Meta

rustc --version --verbose:

rustc 1.85.0-nightly (dff3e7ccd 2024-11-26)
binary: rustc
commit-hash: dff3e7ccd4a18958c938136c4ccdc853fcc86194
commit-date: 2024-11-26
host: x86_64-pc-windows-msvc
release: 1.85.0-nightly
LLVM version: 19.1.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-borrow-checkerArea: The borrow checkerC-bugCategory: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.fixed-by-poloniusCompiling with `-Zpolonius` fixes this issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions