Description
Once support for '_
lands in #44691, the next step for #44524 is to implement a lint that warns against "single use" lifetime names.
Current status
The lint is partially implemented but needs to be completed. Here is a checklist:
- Issue warnings at the right times; this gist provides a comprehensive test case.
- "Warning: never used at all" falls under
unused_lifetimes
- For each warning, issue a suggested fix:
- For a single-use lifetime
'a
appearing in&'a T
, suggest&T
- For a single-use lifetime
'a
appearing in any other place, suggest'_
- One challenge: the binder must be removed too
- cc @estebank -- is it possible to give suggested fixes that make changes to multiple spots at once? I guess that might just be multiple suggestions?
- [] We'll know this is really done when we can enable by default in rustc crates and apply rustfix with suggestions
Older Background
The idea is that an explicit name like 'a
should only be used (at least in a function or impl) to link together two things. Otherwise, you should just use '_
to indicate that the lifetime is not linked to anything.
Until #15872 is closed, we should only lint for single-use lifetime names that are bound in functions. Once #15872 is closed, we can also lint against those found in impl headers.
We can detect cases where a lint is valid by modifying the resolve_lifetimes
code:
- This code basically walks over the HIR and resolves all lifetime names.
- It maintains a stack of scopes indicating what names are valid.
- The function
with()
is used to push new scopes on the stack. It is also given a closure which will execute with the new name bindings in scope.with()
gets called for impls and other kinds of items from here; for methods and functions in particular it is called fromvisit_early_late
).
- Once a name is in scope,
resolve_lifetime_ref()
is called to resolve an actual reference to a named lifetime.- This could be used, for example, to update some information in the
Scope
, e.g. counting how many times a particular lifetime was referenced.
- This could be used, for example, to update some information in the
- Then, before
with()
returns, we could scan the lifetimes and check for those that were only referenced 1 time (or 0 times...) and issue a lint warning.
(There are some directions for how to add a lint under the header "Issuing future compatibility warnings" in the rustc-bug-fix-procedure page on forge -- we can skip the "future compatibility" parts here.)
Activity
cramertj commentedon Sep 22, 2017
Also, I believe, only for lifetime names that appear in argument position. Currently we require explicitly binding output-only lifetimes with a name:
nikomatsakis commentedon Sep 22, 2017
@cramertj Hmm. I would consider the proper way to declare
bar()
to probably befn bar() -> &'static u8
, really, though there are subtleties involved in rare cases (e.g., around invariance).cramertj commentedon Sep 22, 2017
@nikomatsakis Yes,
'static
is the right thing to use. I wanted to point out that we shouldn't recommend'_
here, as it won't work.[-]Lint against single-use lifetime names[/-][+]In-band lifetimes: Lint against single-use lifetime names[/+]gaurikholkar-zz commentedon Sep 30, 2017
Is this up for grabs?
cramertj commentedon Oct 3, 2017
@gaurikholkar Go for it!
gaurikholkar-zz commentedon Oct 3, 2017
Will start working on it
nikomatsakis commentedon Oct 16, 2017
@gaurikholkar hey, just checking in! How's it going? Any blockers?
nikomatsakis commentedon Oct 31, 2017
Some examples:
This should lint against
'x
and suggest&u32
instead.This should lint against
'x
and suggestFoo<'_>
instead.This should lint against
'y
and suggestFoo<'x, '_>
instead.This should lint against
'x
and suggestFoo<'_, 'y>
instead.This should not lint, because
'x
appears only in the return type.This should not lint, because at present
'_
does not work in that position (which we should fix).66 remaining items
[chore]: link false-positive issue
[chore]: link false-positive issue
[chore]: link false-positive issue
[chore]: link false-positive issue
[chore]: link false-positive issue
[chore]: link false-positive issue
[chore]: link false-positive issue
feat: improve config debug-ability (#4456)
joshtriplett commentedon Aug 26, 2024
Summarizing the current state of this:
anonymous_lifetime_in_impl_trait
anonymous_lifetime_in_impl_trait
doesn't have a tracking issue, but Stabilizeanonymous_lifetime_in_impl_trait
#107378 proposes stabilization of it.anonymous_lifetime_in_impl_trait
#107378 is blocked on a concern about interaction with GATs. There are some suggestions to reduce the scope of what's being stabilized, but I wasn't clear on the state of that.anonymous_lifetime_in_impl_trait
also has an ICE: ICE with anonymous_lifetime_in_impl_trait feature: "calledOption::unwrap()
on aNone
value" #124340I think to make forward progress on this:
zacknewman commentedon Jun 23, 2025
Is the following a "false positive"?
Existing code is the following:
Code that uses it looks like below:
If
Foo::new
is changed to accommodate the lint, thenexample1
andexample2
do not compile.