Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upNon-lexical borrow scopes and better treatment of nested method calls #811
Comments
pnkfelix
added
the
postponed
label
Feb 5, 2015
nikomatsakis
referenced this issue
Apr 16, 2015
Closed
borrow scopes should not always be lexical #6393
nikomatsakis
changed the title
Single-entry / multiple-exit regions for borrows
Non-lexical borrow scopes and better treatment of nested method calls
Apr 16, 2015
nikomatsakis
referenced this issue
Apr 16, 2015
Closed
Nested method calls with `&mut` receivers result in borrowck errors #6268
pythonesque
referenced this issue
May 31, 2015
Closed
Should link to improved long-form error for nonlexical borrows #25913
bluss
referenced this issue
Jun 11, 2015
Closed
Call to FnMut closure borrows closure too early #26193
steveklabnik
added a commit
to steveklabnik/rust
that referenced
this issue
Jun 12, 2015
steveklabnik
added a commit
to steveklabnik/rust
that referenced
this issue
Jun 12, 2015
This comment has been minimized.
This comment has been minimized.
|
@mike-marcacci pointed out that the if let Some(val) = map.get_mut(&id) {
/* ... */
} else {
map.insert(id, new_val);
}seems "innocent", it is actually just a syntax sugar for the |
thepowersgang
added a commit
to thepowersgang/rust
that referenced
this issue
Jul 25, 2015
alexcrichton
referenced this issue
Aug 10, 2015
Closed
Borrow checker overly conservative when assigning to a parent reference #27614
This comment has been minimized.
This comment has been minimized.
flavius
commented
Sep 13, 2015
|
What's the state of this feature? Any new plans and/or changes with this? |
This comment has been minimized.
This comment has been minimized.
|
@flavius basically, the HIR/MIR work needs to be completed first. |
oli-obk
referenced this issue
Nov 4, 2015
Closed
[Proposal] bindable expression in `if let` must be available to borrow in else branch #1330
Manishearth
referenced this issue
Nov 22, 2015
Closed
False borrow checker error: cannot use `self.x` because it was mutably borrowed #29975
alexcrichton
referenced this issue
Dec 5, 2015
Closed
Early returns can cause borrows to last until the end of a function #30223
This comment has been minimized.
This comment has been minimized.
ebiggers
commented
Feb 21, 2016
|
I would like to see this implemented. I believe I ran into this with the following code which is descending a prefix tree and inserting new nodes:
The problematic line is this one:
This causes the Rust compiler to spew a page of errors:
This can be "fixed" by replacing the line with this:
In my opinion this adds no value and simply serves as a means of appeasing the borrow checker. The program is correct either way; it seems to be purely a limitation of the borrow checker that it cannot determine this and the programmer has to explicitly add a temporary variable. I understand there may be concern about making the borrow checker more complicated. However, I feel that usability takes precedence here. It's no secret that writing code the Rust compiler can prove is "safe" is one of the largest barriers to using Rust. Any change that makes the compiler smarter and able to correctly recognize more safe code as safe is, in my opinion, an improvement (at least, provided that it continues to follow well-defined rules). |
This comment has been minimized.
This comment has been minimized.
|
Your issue here is reborrow vs. move, which is distinct from non-lexical borrows. You can also move |
This comment has been minimized.
This comment has been minimized.
ehiggs
commented
Mar 21, 2016
|
Is this related to places where matching an option won't compile using e.g. code like this can fail because match foo.as_mut() {
Some(x) => x.bar(), // fn bar(&mut self)
None => foo = Some(Foo::new(7))
} It can be worked around like match foo {
Some(ref mut x) => x.bar(),
None => foo = Some(Foo::new(7))
} |
This comment has been minimized.
This comment has been minimized.
|
That's a different issue - non-lexical borrows. |
This comment has been minimized.
This comment has been minimized.
ehiggs
commented
Mar 22, 2016
This comment has been minimized.
This comment has been minimized.
|
@arielb1 The title of this issue is "Non-lexical borrow scopes and"... |
This comment has been minimized.
This comment has been minimized.
bluss
commented
Mar 22, 2016
|
@ehiggs I wouldn't call that a work around, it's the idiomatic solution. |
This comment has been minimized.
This comment has been minimized.
|
Oops wrong RFC - I thought this was copy-vs-move. |
SimonSapin
referenced this issue
Apr 20, 2016
Merged
Version 1.0, rewrite the data structure and API #176
steveklabnik
referenced this issue
May 9, 2016
Closed
Incorrect "does not live long enough" with stdin().lock().lines() #33520
apasel422
referenced this issue
Jun 2, 2016
Open
Immutable borrow as argument for mutable borrow does not compile #34035
This comment has been minimized.
This comment has been minimized.
|
Think this is related:
|
This comment has been minimized.
This comment has been minimized.
dbrgn
commented
Jul 19, 2016
|
@aidanhs no, I think that is correct. If you visualize the implicit scopes: fn main() {
let mut a = 1;
{
let c;
{
let b = &mut a;
{
c = &*b;
}
}
let d = &a;
}
}...then you can see that you're trying to borrow While borrowing a mutable reference to a value, that refrence is the only way to access that value at all. |
rkruppe
referenced this issue
Sep 12, 2016
Closed
Allow to forget about borrowing outside scoping #36422
This comment has been minimized.
This comment has been minimized.
ebkalderon
commented
Oct 17, 2016
|
Just curious, what is the current status of this issue? Will work on non-lexical borrows resume now that MIR has landed on Nightly? |
This comment has been minimized.
This comment has been minimized.
|
Not sure if that was intentional or not, but beta and nightly allow the following piece of code to work (not panic at runtime): use std::cell::RefCell;
fn main() {
let mut data = RefCell::new(None);
let inner = if data.borrow().is_none() {
let d = 1337;
*data.borrow_mut() = Some(d);
d
} else {
data.borrow().unwrap()
};
}(found here: http://stackoverflow.com/questions/40482981/if-condition-remains-borrowed-in-body ) |
This comment has been minimized.
This comment has been minimized.
|
It was intentional, the previous behavior was a long-standing bug that was only partially fixed before. |
bluss
referenced this issue
Nov 11, 2016
Closed
Can't borrow mutably to calculate argument to method with mutable borrow. #37706
Stebalien
referenced this issue
Nov 13, 2016
Closed
borrow checker does not work correctly with explicit return statements inside for-in loops #37737
This comment has been minimized.
This comment has been minimized.
radix
commented
Dec 2, 2016
|
Can this ticket be closed? I see that all three of the linked issues in the description are closed. If it still needs to be open, is it also still appropriate to have the "postponed" label? |
This comment has been minimized.
This comment has been minimized.
istankovic
commented
Dec 2, 2016
|
@radix The issue #29775 was linked to this one and closed at some point, however, I've just checked and it is still relevant. So if this one is to be closed, I suggest to reopen #29775 since it is stil relevant and represents a very basic use case. |
This comment has been minimized.
This comment has been minimized.
Why would we close it?
That's because they're duplicates of this one.
Yes, as generally this means "we considered it but decided that it's not the right time yet." This is still true, as porting the borrowck to MIR is still a blocker. |
This comment has been minimized.
This comment has been minimized.
radix
commented
Dec 2, 2016
|
@steveklabnik I apologize. I was just unclear on the status since recent comments seemed to indicate it, or some parts of it, had been fixed. I also didn't realize that the links in the description were duplicates, I assumed they were dependents. My error. I should have worded my message more carefully. I didn't mean to say that I think it should be closed, just that I was curious about its status. Thank you for the information. @istankovic I'm not sure which #29775 you are referring to, as I can't find a reference to that number on this page. |
This comment has been minimized.
This comment has been minimized.
istankovic
commented
Dec 2, 2016
|
@radix sorry, I meant rust-lang/rust#29975 |
This comment has been minimized.
This comment has been minimized.
|
@radix it's all good! This is a very long-running and complicated issue, it's very easy to have done that. |
sfackler
referenced this issue
Dec 4, 2016
Closed
Borrow checker: borrows in else branch of if let #38159
rkruppe
referenced this issue
Dec 26, 2016
Closed
`for` borrowing lasts after the end of the for loop #38614
This comment has been minimized.
This comment has been minimized.
|
A rather long write-up about nested method calls specifically: https://internals.rust-lang.org/t/accepting-nested-method-calls-with-an-mut-self-receiver/4588 |
carols10cents
referenced this issue
Feb 2, 2017
Closed
Need common pitfalls for the borrow checker and how to get around them. #426
SimonSapin
referenced this issue
Mar 6, 2017
Closed
Returning a borrowed value extends the borrow to the end of the function #40307
This comment has been minimized.
This comment has been minimized.
What’s the status on this? As far as I can tell, borrows being lexical means not only that some programs need to be more verbose, but also that some programs are impossible (at least with the desired API/characteristics). For example, I just tried to write something like this (reduced here): pub enum Token {
Whitespace,
Ident(String),
Number(i32),
}
pub struct Parser {
/* ... */
}
impl Parser {
pub fn advance_without_skipping_whitespace(&mut self) -> &Token {
unimplemented!()
}
pub fn advance(&mut self) -> &Token {
loop {
match self.advance_without_skipping_whitespace() {
&Token::Whitespace => {}
result => return result
}
}
}
}… and got this error message: error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> <anon>:18:19
|
18 | match self.advance_without_skipping_whitespace() {
| ^^^^
| |
| second mutable borrow occurs here
| first mutable borrow occurs here
...
23 | }
| - first borrow ends here
error: aborting due to previous errorThe problem is the "first" borrow lasting for the whole function rather than just one iteration of the loop. I think that’s because the borrowed value is (in some code paths) returned, and borrow are lexical? I can’t find a way to rewrite this that compiles in today’s Rust, even tail recursion has the same problem as a loop. |
This comment has been minimized.
This comment has been minimized.
That may have been a bit over-dramatic, I found a work-around. (Not returning the result of But the same kind of issues happen all the time when porting existing parsing code to this new API. Enough that this approach is not viable, I may have to do somewhat-expensive cloning everywhere. |
This comment has been minimized.
This comment has been minimized.
It is in-progress. Some steps have recently landed, but its not 100% working yet. |
xftroxgpx
referenced this issue
Aug 15, 2017
Closed
return x; and x not equivalent at end of function? #43837
This comment has been minimized.
This comment has been minimized.
|
I think we can basically close this in favor of rust-lang/rust#43234 |
pnkfelix commentedFeb 5, 2015
•
edited by nikomatsakis
In general, it can be useful to have support for borrows that aren't tied to lexical scopes.
Related links:
&mutreceivers result in borrowck errors (rust-lang/rust#6268)&mut selfreceiver"UPDATE: The relevant RFCs have been accepted. See rust-lang/rust#43234 to track implementation progress here.