There is a minimal repro at https://github.com/rust-lang/rust/issues/67222#issuecomment-564506501 by @andreytkachenko
Sorry for the unclear title, but I found it hard to explain the situation I'm in. The following code leads to an E0597 error
use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
fn main() {
let mut s: HashMap<String, String> = HashMap::new();
s.insert("a".to_owned(), "aa".to_owned());
s.insert("b".to_owned(), "bb".to_owned());
let mut s = Rc::new(RefCell::new(s));
if let Some(o) = s.borrow().get("a") {
println("{}, o);
}
else {
// DO NOTHING
}
}
Which leads to:
error[E0597]: `s` does not live long enough
--> src/main.rs:10:22
|
10 | if let Some(o) = s.borrow().get("a") {
| ^---------
| |
| borrowed value does not live long enough
| a temporary with access to the borrow is created here ...
...
16 | }
| -
| |
| `s` dropped here while still borrowed
| ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, std::collections::HashMap<std::string::String, std::string::String>>`
|
However, if I add some more statement before the main function ends, even a totally irrelevant print statement, the error disappear.
use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
fn main() {
let mut s: HashMap<String, String> = HashMap::new();
s.insert("a".to_owned(), "aa".to_owned());
s.insert("b".to_owned(), "bb".to_owned());
let mut s = Rc::new(RefCell::new(s));
if let Some(o) = s.borrow().get("a") {
println("{}, o);
}
else {
// DO NOTHING
}
println("hello!"); // <----- This line added!!
}
The platform is as follow:
5.0.0-37-generic #40~18.04.1-Ubuntu SMP Thu Nov 14 12:06:39 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
And the rustc version: rustc 1.41.0-nightly (7dbfb0a8c 2019-12-10)
Thanks!
Adding a semicolon after the else clause resolves this. I believe this might be related to https://github.com/rust-lang/rust/issues/21114.
Minimal repro:
fn main() {
let s = std::cell::RefCell::new(Some(()));
if let Some(_) = s.borrow().as_ref() {} else {} // add `;` to make it compilable
}
PS: I suspect - it has some tiny relation to #53528
Thanks, I've changed the issue title to match the minimal repro
The code and diagnostic reported in the original issue are wrong. Fixing the code yields this diagnostic:
error[E0597]: `s` does not live long enough
--> src/main.rs:10:22
|
10 | if let Some(o) = s.borrow().get("a") {
| ^---------
| |
| borrowed value does not live long enough
| a temporary with access to the borrow is created here ...
...
16 | }
| -
| |
| `s` dropped here while still borrowed
| ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, std::collections::HashMap<std::string::String, std::string::String>>`
|
= note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
The note at the end perfectly explains why this fails to compile and how to fix it. Closing.
The code and diagnostic reported in the original issue are wrong. Fixing the code yields this diagnostic:
error[E0597]: `s` does not live long enough --> src/main.rs:10:22 | 10 | if let Some(o) = s.borrow().get("a") { | ^--------- | | | borrowed value does not live long enough | a temporary with access to the borrow is created here ... ... 16 | } | - | | | `s` dropped here while still borrowed | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, std::collections::HashMap<std::string::String, std::string::String>>` | = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.The
noteat the end perfectly explains why this fails to compile and how to fix it. Closing.
Ok, somehow i had missed the note..... still I wander if it is a stable behavior, and if so, is it documented somewhere?
It's documented here: https://doc.rust-lang.org/stable/reference/expressions.html#temporary-lifetimes
The text doesn't account for function bodies also being blocks, however. Feel free to send a PR to the reference changing the wording there.
@jonas-schievink
Besides, other than adding the semicolon, adding a new line of statement also make it compilable. I feel like this is somewhat inconsistent. Shouldn't it yield the same error E0597 after adding that statement?
That also makes it no longer the trailing expression in the block