rust-lang / rust-lang/rust

`mismatched_lifetime_syntaxes` should just say "hidden lifetime parameters are deprecated"

Open
#149,668 0 comments 7 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code
pub struct Abc {
    a: i32,
}

impl Abc {
    pub fn iter(&self) -> std::slice::Iter<i32> {
        std::slice::from_ref(&self.a).iter()
    }
}
Current output
warning: hiding a lifetime that's elided elsewhere is confusing
 --> src/lib.rs:6:17
  |
6 |     pub fn iter(&self) -> std::slice::Iter<i32> {
  |                 ^^^^^     ^^^^^^^^^^^^^^^^^^^^^ the same lifetime is hidden here
  |                 |
  |                 the lifetime is elided here
  |
  = help: the same lifetime is referred to in inconsistent ways, making the signature confusing
  = note: `#[warn(mismatched_lifetime_syntaxes)]` on by default
help: use `'_` for type paths
  |
6 |     pub fn iter(&self) -> std::slice::Iter<'_, i32> {
  |                                            +++
Desired output
warning: hidden lifetime parameters are deprecated
 --> src/lib.rs:6:17
  |
6 |     pub fn iter(&self) -> std::slice::Iter<i32> {
  |                 ^^^^^     -----------------^--- expected a lifetime parameter here
  |                 |
  |                 a lifetime is elided here
  |
  = help: types with hidden lifetimes look like owned types and are confusing when used with elided lifetimes
  = note: `#[warn(mismatched_lifetime_syntaxes)]` on by default
help: use `'_` for types to show they are borrowed
  |
6 |     pub fn iter(&self) -> std::slice::Iter<'_, i32> {
  |                                            +++
Rationale and extra context

According to the 1.89 release post, the whole rationale for mismatched_lifetime_syntaxes is that we want to deprecate hidden lifetimes entirely (the lint elided_lifetimes_in_paths) but it's too much to do all at once. So there is a clear goal in mind. Rustc has tried to get closer by recognising a difference between hidden and elided lifetimes.

Unfortunately this implementation strategy has leaked into the error message. I think that the error message for mismatched_lifetime_syntaxes is really hard to get your head around. Even if this is a less bothersome/frequent/annoying and more focused/useful lint than elided_lifetimes_in_paths, it is about 20x harder to understand why the compiler is warning you.

One lint is a subset of the other. We can very directly compare them. This is elided_lifetimes_in_paths at 1.91.1, minus the 'where lint is declared' part:

error: hidden lifetime parameters in types are deprecated
 --> thing.rs:2:37
  |
2 | fn yeah(x: &u32) -> std::slice::Iter<u32> {
  |                     ----------------^---- expected lifetime parameter
  |
help: indicate the anonymous lifetime
  |
2 | fn yeah(x: &u32) -> std::slice::Iter<'_, u32> {
  |                                      +++

My reaction to each diagnostic is:

  • elided_lifetimes_in_paths: "hidden lifetime parameters in types are deprecated"
    • Instant comprehension. No new concepts. Very simple remedy: stop hiding your lifetimes in types. It's a simple rule you can follow to write clearer code.
  • mismatched_lifetime_syntaxes: "hiding a lifetime that's elided elsewhere is confusing"
    • I think... what is the difference between hiding and eliding? Which one is which? I would have guessed that these are synonyms.
    • Which the error message has had to prepare for... "this one's hiding, this one's eliding"
    • And then the kicker: Hint: the same lifetime is referred to in inconsistent ways...
    • To which I think... Uh, no, the lifetime is not referred to at all! There is not a single piece of lifetime syntax here.
    • So:
      • Long time to understand what I did wrong
      • Hint makes comprehension harder by being wrong
      • Error message is phrased with no clear directive for avoiding this error in future
      • Objectively, we have actually observed users feel bad when they see it. I think it's because "this is confusing" is not neutral enough, it's a criticism of the code. https://github.com/rust-lang/rust/issues/145312

I think we can do better. I think we should just say "hidden lifetimes are deprecated", because it is the attitude you want users to adopt anyway. The way we managed to detect a confusing use of them is not important to the programmer. I think this should be an implementation detail. You can use the other lifetimes it mismatches with to pluck out some context, and that remains useful. I also think the lint can use this to show users why we have decided to deprecate, better than elided_lifetimes_in_paths ever could. I think this phrasing is also less liable to sound judgmental, because "x is deprecated" is not an accusation.

Other background

RalfJung explains hidden vs elided lifetimes in https://github.com/rust-lang/rust/issues/145312#issuecomment-3214591268. It's a fine shade between these two concepts, but sure, it exists.

Other cases

Rust Version
rustc 1.91.1 (ed61e7d7e 2025-11-07)
binary: rustc
commit-hash: ed61e7d7e242494fb7057f2657300d9e77bb4fcb
commit-date: 2025-11-07
host: x86_64-unknown-linux-gnu
release: 1.91.1
LLVM version: 21.1.2
Anything else?

No response

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 diagnostic from the issue's src/lib.rs example with rustc 1.91.1, then locate the implementation and tests for the mismatched_lifetime_syntaxes lint. Done means the warning uses the proposed hidden-lifetime wording, spans and help text match the desired output, and existing diagnostic tests pass.

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.