Description
Universal error types like anyhow::Error
typically require that the wrapped error be 'static
, to avoid lifetime annotations in the overwhelmingly common case.
Some libraries, such as zerocopy
and nom
, routinely return non-static error values that borrow from an input value. If a 'static
error is needed, the expectation is that the user will convert the error value to something more suitable, via map_err
or similar.
(While a static input would result in an error value that satisfies 'static
, that is usually impractical.)
When using the ?
operator to try to convert one of those non-static errors to a universal error that requires 'static
, without an intermediate conversion to something that is static, the resulting lifetime error tends to be technically-correct but very confusing:
use anyhow; // 1.0.95
use zerocopy; // 0.8.16
use zerocopy::TryFromBytes;
pub fn main() -> anyhow::Result<()> {
let input: Vec<u8> = vec![];
let _ = u64::try_read_from_bytes(&input)?;
Ok(())
}
Actual error
(Stable Rust 1.84.1, via playground)
error[E0597]: `input` does not live long enough
--> src/main.rs:8:38
|
7 | let input: Vec<u8> = vec![];
| ----- binding `input` declared here
8 | let _ = u64::try_read_from_bytes(&input)?;
| -------------------------^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `input` is borrowed for `'static`
9 | Ok(())
10 | }
| - `input` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground` (bin "playground") due to 1 previous error
The compiler's implied reasoning here is:
- To satisfy conversion to
anyhow::Error
, the error value must be'static
. - The error value is not
'static
, so there is a problem. - The error value would be static, if only
input
were static. - Therefore, the problem is that
input
doesn't live long enough.
This is confusing, because making input
live for 'static
is unlikely to be a reasonable solution.
Expected error
The compiler should point out that the original error type is not 'static
, which is required by the conversion, and suggest using map_err
to convert it into something that is static.