`mismatched_lifetime_syntaxes` should just say "hidden lifetime parameters are deprecated"
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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