Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upBorrow checker extends borrow range in code with early return #54663
Comments
This comment has been minimized.
This comment has been minimized.
matthewjasper
added
A-NLL
NLL-deferred
labels
Sep 29, 2018
This comment has been minimized.
This comment has been minimized.
CodeSandwich
commented
Sep 29, 2018
•
|
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. |
This comment has been minimized.
This comment has been minimized.
i30817
commented
Sep 29, 2018
•
|
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. |
This comment has been minimized.
This comment has been minimized.
|
I think #51826 suggests that this isn't solved by NLL? |
matthewjasper
added
NLL-polonius
and removed
NLL-deferred
labels
Dec 1, 2018
This comment has been minimized.
This comment has been minimized.
xftroxgpx
commented
Jan 7, 2019
•
|
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: |
This comment has been minimized.
This comment has been minimized.
|
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? |
CodeSandwich commentedSep 29, 2018
•
edited
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