Consider this snippet:
use thiserror::error;
pub fn parse_something(input: &str) -> Result<i32, MyError> {
let (_, number) = nom::number::complete::i32(input)?;
Ok(number)
}
// define error
#[derive(Error, Debug, PartialEq)]
pub enum MyError {
#[error("Parsing error in the input")]
ParseError(#[from] nom::Err<nom::error::Error<&'static str>>),
}
It won't compile because apparently the
borrowed data escapes outside the function
I'm a bit stumped. I just want to catch all the parsing errors in a nice way and return that variant.
I could always use map_err in parse_something, but I thought the #[from] macro exists precisely so I don't have to do it manually.
The reason it's not working in your snippet is because the lifetime of
inputis elided, so the Rust compiler assigns a distinct lifetime (e.g.'a) toinput. Your function (after expanding the lifetime) looks like this to the compiler:The lifetime
'a, unless manually specified by you, is assumed to be shorter than'static. The error is expecting the lifetime of its&strto be'static, so the elided lifetime is too short, and the compiler complains.As you probably found if you tried giving the error any lifetime shorter than
'static,thiserrordoesn't let you give references any non-static lifetimes becausestd::error::Error requires the source is dyn Error + 'static. So, non-static lifetimes are out of the window as well.To fix this, you need to make
inputhave a'staticlifetime. This snippet below compiles:It may not be possible to have
inputbe'static, though. In cases whereinputis not static, you will need to map the error into a type that contains aString. It could look something like this:You can find some more information about difficulty dealing with
nom's errors in this post on the Rust forums.