Skip to content

Adding use std::error::Error unexpectedly breaks lifetime inference #141673

@phip1611

Description

@phip1611

I tried this code:

// As soon as the next line is uncommented, the code doesn't compile.
// use std::error::Error;

fn main() {
    let error = std::fs::File::open("afaf").unwrap_err();
    // Using the fully qualified path here is fine
    let error: &dyn std::error::Error = &error;
    // This line fails to compile with above's `use`
    std::iter::successors(Some(error), |sub_error| sub_error.source()).for_each(|error| {
        eprintln!("{}", error);
    });
}

Link to Rust Playground

I expected this to compile the same way regardless of whether use std::error::Error; is present.

This expectation holds because Error is used later in the code via its fully qualified name (std::error::Error) only, and the use statement should not affect type inference or lifetime resolution.

Instead, this happened:

When the use line is present, the compiler reports a lifetime error:

 --> src/main.rs:7:52
  |
7 |     std::iter::successors(Some(error), |sub_error| sub_error.source()).for_each(|error| {
  |                                         ---------- ^^^^^^^^^^^^^^^^^^ 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`

Removing the use line eliminates the error, without changing any other code.

Meta

This bug happens at least with

  • Rust stable: 1.87 and 1.58 (across editions!)
  • Rust nightly: 1.89.0-nightly (45f256d 2025-05-27)

From a quick research, I didn't find a duplicate of this.

Activity

added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on May 28, 2025
workingjubilee

workingjubilee commented on May 28, 2025

@workingjubilee
Member

...??? some extremely niche case of method res?

added
A-lifetimesArea: Lifetimes / regions
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
T-typesRelevant to the types team, which will review and decide on the PR/issue.
on May 28, 2025
theemathas

theemathas commented on May 28, 2025

@theemathas
theemathas

theemathas commented on May 28, 2025

@theemathas
Contributor

Smaller reproduction:

mod my_mod {
    pub trait Trait {
        fn chain(&self) -> &i32 {
            unimplemented!()
        }
    }
    impl<T: ?Sized> Trait for &T {}
}

// removing this line makes it compile
use my_mod::Trait;

fn foo<'a, 'b>(x: &'a &'b dyn my_mod::Trait) -> &'b i32 {
    x.chain()
}
theemathas

theemathas commented on May 28, 2025

@theemathas
Contributor

The workaround in the original reproducer is to write (*sub_error).source() instead of sub_error.source()

added
C-discussionCategory: Discussion or questions that doesn't represent real issues.
and removed
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
C-bugCategory: This is a bug.
on Jun 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lifetimesArea: Lifetimes / regionsA-type-systemArea: Type systemC-discussionCategory: Discussion or questions that doesn't represent real issues.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @phip1611@theemathas@workingjubilee@rustbot@Noratrieb

        Issue actions

          Adding `use std::error::Error` unexpectedly breaks lifetime inference · Issue #141673 · rust-lang/rust