Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
phip1611 opened this issue May 28, 2025 · 4 comments
Open

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

phip1611 opened this issue May 28, 2025 · 4 comments
Labels
A-lifetimes Area: Lifetimes / regions A-type-system Area: Type system C-discussion Category: Discussion or questions that doesn't represent real issues. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@phip1611
Copy link

phip1611 commented May 28, 2025

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.

@phip1611 phip1611 added the C-bug Category: This is a bug. label May 28, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label May 28, 2025
@workingjubilee
Copy link
Member

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

@workingjubilee workingjubilee added A-type-system Area: Type system A-lifetimes Area: Lifetimes / regions T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue. labels May 28, 2025
@theemathas

This comment has been minimized.

@theemathas
Copy link
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
Copy link
Contributor

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

@Noratrieb Noratrieb added C-discussion Category: Discussion or questions that doesn't represent real issues. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. C-bug Category: This is a bug. labels Jun 1, 2025
phip1611 added a commit to phip1611/cloud-hypervisor that referenced this issue Jun 3, 2025
While working on this, I found a subtle but severe Rust compiler bug [0].
To fight the bug with explicitness rather than implicitness (to prevent
weird stuff in the future), this change is beneficial.

The bug is at least in Rust stable 1.34..1.87.

[0]: rust-lang/rust#141673

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
phip1611 added a commit to phip1611/cloud-hypervisor that referenced this issue Jun 3, 2025
While working on this, I found a subtle but severe Rust compiler bug [0].
To fight the bug with explicitness rather than implicitness (to prevent
weird stuff in the future), this change is beneficial.

The bug is at least in Rust stable 1.34..1.87.

[0]: rust-lang/rust#141673

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lifetimes Area: Lifetimes / regions A-type-system Area: Type system C-discussion Category: Discussion or questions that doesn't represent real issues. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants