rust-lang / rust-lang/rust

Confusing diagnostic when the error value converted by `?` fails to satisfy a `'static` bound

Open
#136,902 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-borrow-checker A-diagnostics A-trait-system D-confusing D-terse T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

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(())
}

(Playground link)

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the example from the linked Rust Playground and inspect the compiler diagnostic path for E0597; the issue names no repository file or test. Compare the current lifetime diagnostic with the requested wording, including identifying the non-'static error and suggesting map_err. Done when a regression test covers the ? conversion and the diagnostic is clearer.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.