rust-lang / rust-lang/rust

Importing `std::error::Error` causes lifetime error to appear in previously compiling code

Open
#154,099 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-trait-system C-bug
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I tried this code:

use std::iter::successors;

use std::error::Error;

pub mod file {
    use std::{error::Error, fs::File};

    pub fn open_non_existent() -> Box<dyn Error> {
        let err = File::open("doesn't exist.jpg").unwrap_err();
        Box::new(err)
    }
}

fn main() {
    let err = file::open_non_existent();

    for part in successors(Some(&*err), |e| e.source()) {
        println!("{}", part);
    }
}

I expected to see this happen: It to compile, since it does with line 3 (use std::error::Error;) commented out

Instead, this happened: A lifetime error appears as long as e is not replaced with (*e)

error: lifetime may not live long enough
  --> src/main.rs:17:42
   |
17 |     for e in successors(Some(&*err), |e| e.source()) {
   |                                       -- ^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
   |                                       ||
   |                                       |return type of closure is Option<&'2 dyn std::error::Error>
   |                                       has type `&'1 &dyn std::error::Error`

error: could not compile `tmp` (bin "tmp") due to 1 previous error
Meta

This happens since version 1.51, where impl<'a, T: Error + ?Sized> Error for &'a T { was added, until nightly.

I'm unsure whether this is maybe even expected behaviour, since I also don't quite understand how source() could even be called without the import (maybe this has something to do with dyn?), since Error is not in the prelude as far as i can see.

rustc --version --verbose:

rustc 1.94.0 (4a4ef493e 2026-03-02)
binary: rustc
commit-hash: 4a4ef493e3a1488c6e321570238084b38948f6db
commit-date: 2026-03-02
host: x86_64-unknown-linux-gnu
release: 1.94.0
LLVM version: 21.1.8

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

Start with the src/main.rs reproducer at the closure on line 17, compiling it with and without the std::error::Error imports and comparing stable, beta, and nightly behavior. Trace the compiler's handling of Error::source and the added impl for &T; done means the regression is explained and covered by a focused compiler test.

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
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.