Skip to content
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

Bug in while let and if let? #30832

Closed
bvssvni opened this issue Jan 11, 2016 · 8 comments
Closed

Bug in while let and if let? #30832

bvssvni opened this issue Jan 11, 2016 · 8 comments
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@bvssvni
Copy link

bvssvni commented Jan 11, 2016

play.rust-lang.org http://is.gd/FWYYn9

use std::rc::Rc;
use std::cell::RefCell;

fn foo(a: &mut u32) -> Option<()> {
    if *a < 10 { *a += 1; Some(()) } else { None }
}

fn main() {
    let a = Rc::new(RefCell::new(4));
    while let Some(()) = foo(&mut *a.borrow_mut()) {
    // Works:
    // while let Some(()) = { let mut b = a.borrow_mut(); foo(&mut *b) } {
        println!("{}", *a.borrow());
    }
}

The RefMut seems to outlive the while let block, instead of just the right expression.

The same happens if you put it in a block, like this:

while let Some(()) = { foo(&mut *a.borrow_mut()) } {

Same problem with if let.

bvssvni added a commit to bvssvni/glium_graphics that referenced this issue Jan 12, 2016
- Bumped to 0.19.0
- Added temporary fix for rust-lang/rust#30832
@steveklabnik
Copy link
Member

/cc @rust-lang/lang

@jonas-schievink
Copy link
Contributor

I blame match desugaring, as always ;)

@pnkfelix
Copy link
Member

This is not a if let or while let issue. You can see the same supposed misbehavior with a direct match:

use std::rc::Rc;
use std::cell::RefCell;

fn foo(a: &mut u32) -> Option<()> {
    if *a < 10 { *a += 1; Some(()) } else { None }
}

fn main() {
    let a = Rc::new(RefCell::new(4));
    loop {
        match foo(&mut *a.borrow_mut()) {
        // works:
        // match { let mut b = a.borrow_mut(); foo(&mut *b) } {
            Some(()) => { println!("{}", *a.borrow()); }
            None => break,
        }
    };
}

I think this is an rvalue-lifetimes issue.

(Furthermore, I think this is expected behavior, but @nikomatsakis is more expert on these matters than I...)

@nikomatsakis
Copy link
Contributor

On Tue, Jan 12, 2016 at 08:28:28AM -0800, Felix S Klock II wrote:

(Furthermore, I think this is expected behavior, but @nikomatsakis is more expert on these matters than I...)

Another way to make the error go away is to change to match { let x = foo(&mut *a.borrow_mut()); x }. I agree this
is the "expected behavior", though it is a common footgun with
RefCell in particular. That is, you are best off always using
borrow expressions like this with a let (as I showed above, though
probably not in a nested block), since otherwise the borrow is held
for the entire match. Not sure if it would be possible to tweak the
rules to avoid this problem; I suspect it'd break code, but we'd have
to experiment to know for sure.

@bvssvni
Copy link
Author

bvssvni commented Jan 13, 2016

@nikomatsakis Thanks for the tip!

@arielb1
Copy link
Contributor

arielb1 commented Jan 13, 2016

We got to have some centralized place to track all annoyances with temporary destruction order rather than leaving them laying around in issues.

@steveklabnik steveklabnik added T-lang Relevant to the language team, which will review and decide on the PR/issue. and removed A-lang labels Mar 24, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 24, 2017
@steveklabnik
Copy link
Member

triage: still an issue, even with NLL

@Mark-Simulacrum
Copy link
Member

I'm going to close in favor of #15023 which is maybe not a great issue for this but seems to fit the bill of "temporary lifetimes are sometimes not quite what one would want".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants