Skip to content

NLL no longer figures out non-lexical lifetimes within loop #51526

Open
@daboross

Description

@daboross

Minimal useful example:

#![feature(nll)]
use std::collections::VecDeque;

fn next(queue: &mut VecDeque<u32>, above: u32) -> Option<&u32> {
    let result = loop {
        {
            let next = queue.front()?;
            if *next > above {
                break next;
            }
        }
        queue.pop_front();
    };
    
    Some(result)
}

This program compiled in nightly-2018-03-07, but does not compile on nightly-2018-05-27. Instead, it fails with this error:

error[E0502]: cannot borrow `*queue` as mutable because it is also borrowed as immutable
  --> src/main.rs:12:9
   |
7  |             let next = queue.front()?;
   |                        ----- immutable borrow occurs here
...
12 |         queue.pop_front();
   |         ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
   |

(playground)

To my understanding, this program is in fact sane. next is always dropped by the time queue.pop_front() runs, and if it escapes and is returned, queue.pop_front() is not run.

The error is the same if return Some(next); is used instead of break next;.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-NLLArea: Non-lexical lifetimes (NLL)C-enhancementCategory: An issue proposing an enhancement or a PR with one.NLL-poloniusIssues related for using Polonius in the borrow checkerT-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