I have a bit of code that I'm fighting with. It's a little helper function that should return a Vec<&str>
to the calling function. I can't seem to get the lifetime right, though.
Here is the code snippet:
fn take_symbol<'a>(ch: &'a str, current: &'a mut String) -> &'a mut TokenList<'a> {
let out = TokenList::<'a>::new();
out.push(current.as_str());
out.push(ch);
*current = String::new();
&mut out
}
The compiler is telling me: error: 'out' does not live long enough
and that the reference must be valid for the lifetime of 'a
, but it looks to me like it is defined for 'a
.
I have also tried changing it to:
let out = &mut TokenList::<'a>::new();
which doesn't change any of the error messages. Or:
let out = &'a mut TokenList::<'a>::new();
which the compiler doesn't like at all.
How do I define out
to have a lifetime of 'a
?
For further details, here is my definition of TokenList:
pub type Token<'a> = &'a str;
pub type TokenList<'a> = Vec<Token<'a>>;
Lifetimes are what the Rust compiler uses to keep track of how long references are valid for. Checking references is one of the borrow checker's main responsibilities. Lifetimes help the borrow checker ensure that you never have invalid references.
A generic lifetime parameter imposes a lifetime constraint on the reference(s) and the return value(s) of a function. While compiling the code, a generic lifetime is substituted for a concrete lifetime, which is equal to the smaller of the passed references' lifetimes.
Rather than ensuring that a type has the behavior we want, lifetimes ensure that references are valid as long as we need them to be. One detail we didn't discuss in the “References and Borrowing” section in Chapter 4 is that every reference in Rust has a lifetime, which is the scope for which that reference is valid.
A static is never "inlined" at the usage site, and all references to it refer to the same memory location. Static items have the static lifetime, which outlives all other lifetimes in a Rust program. Static items may be placed in read-only memory if the type is not interior mutable.
The lifetime of out
is not 'a
, since out
is destroyed at the end of the function. Rust will not allow you to return a reference to it (it would allow accessing freed memory!).
Try changing your function to the following:
fn take_symbol<'a>(ch: &'a str, current: &'a mut String) -> TokenList<'a> {
let out = TokenList::<'a>::new();
out.push(current.as_str());
out.push(ch);
*current = String::new();
out
}
This way you will pass the ownership of out
to the caller and it will live long enough.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With