Skip to content

rustc suggests for<'a> when lifetime param already exists #123713

Description

@Rudxain

Code

fn abs<'a, T>(x: &'a T) -> T
where
    &'a T: Ord + core::ops::Neg<Output = &T>,
    T: Clone,
{
    x.max(-x).clone()
}

Current output

Compiling playground v0.0.1 (/playground)
error[E0637]: `&` without an explicit lifetime name cannot be used here
 --> src/lib.rs:3:42
  |
3 |     &'a T: Ord + core::ops::Neg<Output = &T>,
  |                                          ^ explicit lifetime name needed here
  |
help: consider introducing a higher-ranked lifetime here
  |
3 |     &'a T: Ord + for<'a> core::ops::Neg<Output = &'a T>,
  |                  +++++++                          ++

For more information about this error, try `rustc --explain E0637`.
error: could not compile `playground` (lib) due to 1 previous error

Desired output

Compiling playground v0.0.1 (/playground)
error[E0637]: `&` without an explicit lifetime name cannot be used here
 --> src/lib.rs:3:42
  |
3 |     &'a T: Ord + core::ops::Neg<Output = &T>,
  |                                          ^ explicit lifetime name needed here
  |
help: consider introducing a higher-ranked lifetime here
  |
3 |     &'a T: Ord + core::ops::Neg<Output = &'a T>,
  |                                           ++

For more information about this error, try `rustc --explain E0637`.
error: could not compile `playground` (lib) due to 1 previous error

Rationale and extra context

Following the compiler's suggestion:

   Compiling playground v0.0.1 (/playground)
error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
 --> src/lib.rs:3:22
  |
1 | fn abs<'a, T>(x: &'a T) -> T
  |        -- first declared here
2 | where
3 |     &'a T: Ord + for<'a> core::ops::Neg<Output = &'a T>,
  |                      ^^ lifetime `'a` already in scope

For more information about this error, try `rustc --explain E0496`.
error: could not compile `playground` (lib) due to 1 previous error

Other cases

No response

Rust Version

From playground:
1.79.0-nightly

(2024-04-08 ab5bda1aa70f707014e2)

Anything else?

No response

Activity

  1. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Apr 10, 2024
  2. added
    A-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`
    D-incorrectDiagnostics: A diagnostic that is giving misleading or incorrect information.
    A-resolveArea: Name/path resolution done by `rustc_resolve` specifically
    A-lifetimesArea: Lifetimes / regions
    on Apr 10, 2024
  3. fmease commented on Apr 10, 2024

    @fmease
    Member

    Slightly relates to #122714. Marking as D-incorrect Diagnostics: A diagnostic that is giving misleading or incorrect information. because introducing for<'a> in the presence of <'a> is not only what the user probably doesn't want but also incorrect because it would shadow the outer lifetime parameter which is forbidden.

    We should walk the lifetime ribs / check the lifetime params in scope.

    If there are multiple lifetime params available or if there are none, we should generally keep suggesting introducing a higher-ranked lifetime param with a fresh name that doesn't clash (*).

    (*) However, in this specific case — an anonymous lifetime inside an assoc type binding / constraint — that would actually be incorrect, too, as it would always be unconstrained (E0582).

    That's gonna be slightly harder to fix (but not impossible) because the check for anonymous lifetimes happens during late resolution (rustc_resolve::late) and we detect unconstrained late bound vars during HIR ty lowering in validate_late_bound_regions (because it requires some more pieces of information not available during late resolution). Either we make use of a heuristic in late (falling back to suggesting adding a lifetime param to the innermost item that can be generic or using 'static which wouldn't be that great) or if feasible we stash the diagnostic and add onto it later during HIR ty lowering.

  4. fmease commented on Apr 10, 2024

    @fmease
    Member

    If there are multiple lifetime params available or if there are none, we should generally keep suggesting introducing a higher-ranked lifetime param with a fresh name that doesn't clash (*).

    Regarding the decision to keep suggesting for<'a> in certain cases: It's often more general. Note that we used to suggest 'static in these positions if I remember correctly — I might be mistaken — and we intentionally changed it to for<'a> ... 'a. Maybe it wasn't an issue but a PR 🤔

  5. fmease commented on Apr 10, 2024

    @fmease
    Member

    (*) However, in this specific case — an anonymous lifetime inside an assoc type binding / constraint — that would actually be incorrect, too, as it would always be unconstrained (E0582).

    Ah, we have already have issue #122025 / PR #123245 for that, I knew I saw an issue related to that.

  6. estebank commented on Apr 11, 2024

    @estebank
    Contributor

    @fmease I think it makes sense to suggest both for<'x> and using the existing 'a, when in doubt. I believe that when we introduced this suggestion first we briefly tried that out. I don't recall why I didn't keep it back then. It might have been that none of the cases in the test suite benefited from not using for<'a>.

  7. added
    D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.
    on Nov 12, 2025
  8. bb1yd commented on Aug 1, 2026

    @bb1yd
    Contributor

    Fixed by PR #156750? But it introduced another bug:

    help: consider introducing a named lifetime parameter
      |
    1 ~ fn abs<'a, 'a, T>(x: &'a T) -> T
    2 | where
    3 ~     &'a T: Ord + core::ops::Neg<Output = &'a T>,

    @rustbot claim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsA-resolveArea: Name/path resolution done by `rustc_resolve` specificallyA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`D-incorrectDiagnostics: A diagnostic that is giving misleading or incorrect information.D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.T-compilerRelevant to the compiler 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

    Issue actions