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

Incorrect "does not live long enough" with stdin().lock().lines() #33520

Closed
LukasKalbertodt opened this issue May 9, 2016 · 3 comments
Closed

Comments

@LukasKalbertodt
Copy link
Member

LukasKalbertodt commented May 9, 2016

fn main() {
    let foo: String = std::io::stdin().lock().lines().nth(0).unwrap().unwrap();
}

leads to

src\main.rs:14:23: 14:39 error: borrowed value does not live long enough                                               
src\main.rs:14     let foo: String = std::io::stdin().lock().lines().nth(1).unwrap().unwrap();                         
                                     ^~~~~~~~~~~~~~~~                                                                  
src\main.rs:14:5: 14:80 note: reference must be valid for the destruction scope surrounding statement at 14:4...       
src\main.rs:14     let foo: String = std::io::stdin().lock().lines().nth(1).unwrap().unwrap();                         
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                         
src\main.rs:14:5: 14:80 note: ...but borrowed value is only valid for the statement at 14:4                            
src\main.rs:14     let foo: String = std::io::stdin().lock().lines().nth(1).unwrap().unwrap();                         
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                         
src\main.rs:14:5: 14:80 help: consider using a `let` binding to increase its lifetime                                  
src\main.rs:14     let foo: String = std::io::stdin().lock().lines().nth(1).unwrap().unwrap();                         
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                         

This doesn't make any sense since foo does not reference any temporary object (like Stdin or StdinLock). It's a String after all, as the optional type annotation shows.

Maybe related to #31439

@frankmcsherry
Copy link
Contributor

The problem here is that std::io::stdin() creates a Stdin, whose lock method needs to borrow itself. However, the lifetime of the Stdin is apparently too short if it isn't bound to anything. You can fix it like so (and maybe await a better explanation):

use std::io::BufRead;

fn main() {
    let bar = std::io::stdin();
    let foo: String = bar.lock().lines().nth(0).unwrap().unwrap();
}

@LukasKalbertodt
Copy link
Member Author

LukasKalbertodt commented May 9, 2016

Yep, that's the fix I currently use. Sorry, should have been more clear about that.

Still: I would expect that rustc automagically creates bindings here, just as in let bar = &3;. I don't know if there is an issue about this already :/

@steveklabnik
Copy link
Member

This is an issue that will be fixed by "non-lexical lifetimes", so I will give it a close, as it falls under that umbrella. The RFC is not yet up, but it is a very desired thing. rust-lang/rfcs#811 is one of the two or three RFC issues on this topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants