The two lifetimes are necessary because you want the struct field to outlive the containing struct. This cannot be achieved with single lifetime for both the struct and its field.
It returns a reference &str that is a field (of a field) of Parser, while the Parser only exists within the function body. In order to make it work, the field of Parser has to borrow a value that has the same lifetime as the return value. That is, as long as the returned value &str has the same lifetime as the input argument context, it does not matter how long the Parser struct lives. In other words, the lifetimes of Parser and context are independent - that is why they have two lifetimes in the struct definition.
To understand it in another way, you can consider the struct constructor of Parser as a new() function, whose input argument has different lifetime than it self's, which is common in function definitions.
impl<'a, 's> Parser<'a, 's> {
//the argument context has lifetime 's and is borrowed for lifetime 'a
fn new(context: &'a Context<'s>)->Parser<'a, 's>{
Parser{context}
}
fn parse(&'a self) -> Result<(), &'s str> {
Err(&self.context.0[1..])
}
}
fn parse_context<'a>(context: Context<'a>) -> Result<(), &'a str> {
Parser::new(&context).parse() //Parser only lives within this scope
}
In this way, it is like that you have an input argument passed to Parser "function", and returns the same argument data. The argument's lifetime has nothing to do with the Parser "function".
Love this article and this additional information is great. Thank you for adding it.
I can deal with most of Rust's idiosyncrasies, but with lifetimes I feel like the compiler leads me by the nose. I do as I'm told without knowing and I hate doing that.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
The two lifetimes are necessary because you want the struct field to outlive the containing struct. This cannot be achieved with single lifetime for both the struct and its field.
In this function:
It returns a reference &str that is a field (of a field) of Parser, while the Parser only exists within the function body. In order to make it work, the field of Parser has to borrow a value that has the same lifetime as the return value. That is, as long as the returned value &str has the same lifetime as the input argument context, it does not matter how long the Parser struct lives. In other words, the lifetimes of Parser and context are independent - that is why they have two lifetimes in the struct definition.
To understand it in another way, you can consider the struct constructor of Parser as a new() function, whose input argument has different lifetime than it self's, which is common in function definitions.
In this way, it is like that you have an input argument passed to Parser "function", and returns the same argument data. The argument's lifetime has nothing to do with the Parser "function".
See the working version in Playground.
Love this article and this additional information is great. Thank you for adding it.
I can deal with most of Rust's idiosyncrasies, but with lifetimes I feel like the compiler leads me by the nose. I do as I'm told without knowing and I hate doing that.