Reputation: 939
I have a very small repo which currently does not compile, with the following error:
error[E0597]: `line` does not live long enough
--> src/main.rs:19:20
|
19 | let line = line.trim();
| ^^^^-------
| |
| borrowed value does not live long enough
| argument requires that `line` is borrowed for `'static`
...
22 | }
| - `line` dropped here while still borrowed
I've had trouble producing a minimal example demoing the problem: this (playground) works as expected, despite that fn main
is identical to the one which fails, as are the signatures of ItemParser::parse
and Item::pretty_to
.
Inlining a section of fn main
, and some signatures:
let parser = ItemParser::new();
let stdin = stdin();
let reader = stdin.lock();
let reader = BufReader::new(reader);
let stdout = stdout();
let mut writer = stdout.lock();
for line in reader.lines() {
let line = line?;
let line = line.trim();
let item = parser.parse(line)?;
item.pretty_to(&mut writer)?;
}
The same issue persists when I comment out item.pretty_to(&mut writer)?;
, so I believe that that isn't the problem.
I can't show the actual code for ItemParser
as it's generated by LALRPOP, but the signature as reported by rustdoc is
pub struct ItemParser { /* fields omitted */ }
pub fn parse<'input>(
&self,
input: &'input str
) -> Result<Item<'input>, ParseError<usize, Token<'input>, &'static str>>
Unlike this issue, nothing in this crate explicitly requires a 'static
lifetime.
My expectation is that at the head of the for
loop, item
has type io::Result<String>
. After we discard the error and trim the edges, it should have type &'a str
, where 'a
is the lifetime scoped to this iteration of the for
loop. In that case, parsing the line should produce an Item<'a>
with the same lifetime. It drops before the lifetime ends, in appropriate sequence. As nothing visibly requests a 'static
lifetime, I don't know where that requirement is coming from.
Upvotes: 4
Views: 258
Reputation: 60082
On error, parser.parse()
yields a type that is bounded to the lifetime of the input.
Result<Item<'input>, ParseError<usize, Token<'input>, &'static str>>
// ^^^^^^^^^^^^^
You're using ?
to return the error from main (not "discard" it), which by necessity will outlive the loop, and therefore line
.
You can handle the error immediately via match
or if let
, or do something like parser.parse().map_err(...)?
to transform the error into something not bounded to the lifetime of line
.
Answering the title specifically, The 'static
requirement is from using eyre::Result
which is an alias for Result<T, E = Report>
. Report
can be created from any Error
type (which ParseError
is), but is constrained to be 'static
. It is a shame the compiler doesn't bring this up though.
Upvotes: 2
Reputation: 8954
Since str
is a sort of slice, it can not outlive its parent. The result on trim is really just a slice the original string.
pub fn trim(&self) -> &str
// Now with the implicit lifetimes
pub fn trim<'a, 'b: 'a>(&'b self) -> &'a str
Since none of the lifetimes of the function arguments would not make appropriate bounds for the lifetime of the function output, it must have a different lifetime and the only appropriate lifetime for an unconstrained reference is 'static
.
Its basically the equivalent to returning a reference to data you just freed in c.
Foo *data_to_return = &foo->bar;
free(foo);
return data_to_return;
But it's kinda a moot point anyway because the function would never work in the first place. The lifetime is more of a symptom of your issue than the cause. Just ignore the lifetime for now since it sounds like its holding you up from actually fixing the issue. Once you fix your code, the 'static
bound will go away.
Upvotes: -1