I'm having some trouble trying to grasp why I can't return an &str
value generated from a String
(goodness, when will as_str
be ready?) and I'm doing something wrong. I get this idea because nothing that I do makes the value live long enough to use.
I'm trying to implement error::Error
for a custom struct:
impl error::Error for LexicalError {
fn description(&self) -> &str {
let s = format!("{}", self);
// s doesn't live long enough to do this, I've tried
// cloning s and using that, but still the clone doesn't
// live long enough.
s.trim()
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
(for the complete snippet, here is the playpen)
I can't figure out how to return an &str from description
, I'd like to reuse the Display
logic, unless of course I'm completely misunderstanding what description
should be returning (perhaps the short description of the issue). Either, I get the same issue with the return of format!(...)
which is a variable I can't seem to get to live long enough to be useful to me.
First, let’s take a look at what lifetime is actually expected. There is an implicit lifetime in the signature of
description
:The returned pointer must be valid for at least as long as
self
. Now considers
. It will hold aString
, an owned string, and it goes out of scope at the end of the function. It would be invalid to return&s
, becauses
is gone when the function returns.trim
returns a string slice that borrowss
, but the slice is again only valid for as long ass
is.You need to return a string slice that outlives the method call, so this rules out anything on the stack. If you were free to choose the return type, a solution would be to move the string out of the function. For that an owned string would be required, and then the return type would be
String
, not&str
. Unfortunately, you are not free to choose the return type here.To return a string slice that outlives the method call, I see two options:
Use a
&'static
string slice. This will certainly outlive the call, but it requires that the string be known at compile time. String literals have type&'static str
. This is a suitable option if the description does not contain any dynamic data.Store an owned string in
LexicalError
itself. This ensures that you can return a pointer to it that is valid for the entire lifetime ofself
. You can add a fielddesc: String
toLexicalError
and do the formatting when the error is constructed. Then the method would be implemented asFor re-use, you can make
Display
write the same string.According to the documentation of
Error
,Display
may be used to provide additional detail. If you wish to include dynamic data in the error, thenDisplay
is a great place to format it, but you can omit it fordescription
. This would allow the first approach to be used.