-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Borrow checker extends borrow range in code with early return #54663
Comments
Thank you for accepting! Should it be a low priority issue? The broken borrowing flow seems simple and is very hard to bypass when needed. |
From my understanding polonius was created to fix this usecase among others since it's very common for terse code. You probably won't get it with NLL, otherwise it would already be there and a major motivation for polonius wouldn't exist. On the other hand, it's very probable that polonius will replace NLL as the default 'NLL 2.0' eventually. tl;dr: this issue is low priority because it's already being acted on and it's not going to be fixed without the lengthy process of making polonius ready to ship as default. My guess is it can't be lifted over as a single feature. Read the blog entry about it here. |
I think #51826 suggests that this isn't solved by NLL? |
tl;dr: this compiles I've this code that seems to be hitting the same (current)issue. In this code I've illustrated 4 cases, 2 of which don't work. I've uncommented block code for case 3 below, but feel free to uncomment only the block for the relevant case you want to see act: #![feature(nll)]
#![nll]
#![allow(dead_code)]
//#[derive(Debug)] //no need for this example
enum Opt<T> {
//a non-Copy Option<T> XXX actually Option<T> is Copy only when T is Copy ; not so for this Opt<T> which is never Copy
Some(T),
None,
}
impl<T> Opt<T> {
#[inline]
pub fn as_mut(&mut self) -> Opt<&mut T> {
match *self {
Opt::Some(ref mut x) => Opt::Some(x),
Opt::None => Opt::None,
}
}
#[inline]
pub fn unwrap(self) -> T {
match self {
Opt::Some(val) => val,
Opt::None => panic!("called `Option::unwrap()` on a `None` value"),
}
}
}
struct WrappedI32(i32); //avoid Copy
struct Foo(Opt<WrappedI32>);
impl Foo { //example stolen&modified from jmcomets from irc
fn get_or_set(&mut self, value: WrappedI32) -> &mut WrappedI32 {
/*match self.0 {//this compiles, but not entirely sure it's equivalent to 'case 4' below
Opt::Some(ref mut value) => return value,
Opt::None => {
self.0 = Opt::Some(value);
self.0.as_mut().unwrap()
}
}*/
{//this doesn't compile: that is, cases 3&4 don't work
//case 1: compiles
/*
let a = self.0.as_mut();
return a.unwrap();
*/
//case 2: compiles
/*
let a = self.0.as_mut();
*/
//case 3: fails to compile
// /*
let a = self.0.as_mut();
if 1 == 2 {
return a.unwrap();
}
// */
//case 4: fails to compile
/*
if let Opt::Some(value) = self.0.as_mut() { //allowing this block compile fails
return value;
}
*/
}
self.0 = Opt::Some(value); //compile fails is here: error[E0506]: cannot assign to `self.0` because it is borrowed
self.0.as_mut().unwrap()
}
}
fn main() {
// ...
} error is like this:
EDIT: Actually maybe it's: |
I ran into this today with https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=06cc9ab7151cd48d162b938e8898639f. Polonius fixes it. Is there a workaround for just NLL? |
This bug just bit me again. It seems this keeps coming up. #84361 shows a number of people being affected by this, and that issue seems to have evaded attention from anyone familiar with the previous reports eg this one. No doubt there are others. Is there anything we could do to improve the UX here? Some heuristic hint in the error message maybe? AFAICT from my reading, it is expected that polonius will fix this. At least, this was expected in 2019... I struggled, and failed, to find out any information about polonius's state and likely future timescale. Searching for issues with |
There isn't much active work on polonius at the moment. |
For the interested, this workaround worked for me: if bar(x).is_some() {
return bar(x).unwrap()
} Caching |
Borrow checker seems to extend mutable borrow of variable to the end of the function in case of an early return of value dependent on the borrow:
Gives:
Compilation fails on stable, nightly and nightly with NLL, works on nightly with polonius.
Try it on Playground
The text was updated successfully, but these errors were encountered: