No explanation for source of static lifetime requirement in E0597
The compiler can do better at indicating the source of the 'static requirement from various sources, including closures passed to functions (e.g., thread::spawn) and Box<Error> having an implicit Error + 'static bound.
Thread::spawn case
This minimized code:
use std::thread;
struct Thing<'a> {
blut: &'a str
}
fn main() {
let dest = String::from("/etc");
let dest = &dest[..];
let thing = Thing { blut: dest };
let t = thread::spawn(|| { thing; });
}
gives the error
error[E0597]: `dest` does not live long enough
--> <source>:9:17
|
9 | let dest = &dest[..];
| ^^^^ does not live long enough
...
12 | }
| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
which is as intended, I think (ending with a ellipsis is a little weird, but it historically was followed by a second note about a "block suffix" which was removed because nobody knows what that means). But it would be great if the error could tell me the two critical pieces of information leading to the error:
- The
'staticrequirement comes fromFinthread::spawn::<F> destis used in the closure because it's in the structthing
Especially number 2 is not obvious at all.
Box<Error> case
(code partially stolen from https://github.com/rust-lang/rust/issues/35580)
use std::error::Error;
struct SomeStruct;
#[derive(Debug)]
enum SomeError<'a> {
Something(&'a str),
Other,
}
fn do_stuff(doc: &usize) -> Result<SomeStruct, SomeError> {
Ok(SomeStruct)
}
fn get_things() -> Result<SomeStruct, Box<Error>> {
let res = try!(Err(SomeError::Other));
Ok(try!(do_stuff(&res)))
}
impl<'a> std::fmt::Display for SomeError<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "blah")
}
}
impl<'a> Error for SomeError<'a> {
fn description(&self) -> &str { "blah" }
}
error: `res` does not live long enough
--> ./test.rs:17:23
|
17 | Ok(try!(do_stuff(&res)))
| ^^^ does not live long enough
18 | }
| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
I've just run into this problem as well. I'm getting the following error message:
error[E0597]: `join` does not live long enough --> src/relation/peerjoin.rs:110:13 | 110 | let x = join.iter_all(); | ^^^^----------- | | | borrowed value does not live long enough | argument requires that `join` is borrowed for `'static` 111 | // assert_eq!(join.iter_all().count(), 3); 112 | } | - `join` dropped here while still borrowedEverything involved here is defined locally.
iter_all()shouldn't requireself:'static, and doesn't appear to at first glance. An audit of all mentions ofstaticin my codebase doesn't turn up anything suspicious, so it is probably an implied bound from somedyn ...orimpl ...clause somewhere. Tracking this down is going to require significant effort when the compiler presumably knows where the problem is coming from.e2-71828 at 2021-02-12 12:22:32
It seems to point out the
thread::spawnnowerror[E0597]: `dest` does not live long enough --> src/main.rs:9:17 | 8 | let dest = String::from("/etc"); | ---- binding `dest` declared here 9 | let dest = &dest[..]; | ^^^^ borrowed value does not live long enough 10 | let thing = Thing { blut: dest }; 11 | let t = thread::spawn(|| { thing; }); | ---------------------------- argument requires that `dest` is borrowed for `'static` 12 | } | - `dest` dropped here while still borrowedFrank Steffahn at 2023-09-03 09:46:47