Repository: rust
Issue: In-band lifetimes: Lint against single-use lifetime names
Labels: A-lints,A-lifetimes,E-mentor,B-RFC-approved,T-compiler,C-tracking-issue,S-tracking-impl-incomplete,F-lint-single_use_lifetimes

Once support for `'_` lands in https://github.com/rust-lang/rust/pull/44691, the next step for https://github.com/rust-lang/rust/issues/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: 

- [x] Issue warnings at the right times; [this gist](https://gist.github.com/nikomatsakis/acdeb20b0192e2a1f404d514b3002c59) provides a comprehensive test case.
  - "Warning: never used at all" falls under `unused_lifetimes`
- [x] 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 https://github.com/rust-lang/rust/issues/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](https://github.com/rust-lang/rust/blob/3cf28f3002470f61a471c69b869e4f55ae1766f7/src/librustc/middle/resolve_lifetime.rs):

- This code basically walks over the HIR and resolves all lifetime names. 
- It maintains a stack of [scopes](https://github.com/rust-lang/rust/blob/3cf28f3002470f61a471c69b869e4f55ae1766f7/src/librustc/middle/resolve_lifetime.rs#L194-L230) indicating what names are valid.
- [The function `with()`](https://github.com/rust-lang/rust/blob/3cf28f3002470f61a471c69b869e4f55ae1766f7/src/librustc/middle/resolve_lifetime.rs#L781-L803) 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](https://github.com/rust-lang/rust/blob/3cf28f3002470f61a471c69b869e4f55ae1766f7/src/librustc/middle/resolve_lifetime.rs#L348-L351); for methods and functions in particular it is called from [`visit_early_late`](https://github.com/rust-lang/rust/blob/3cf28f3002470f61a471c69b869e4f55ae1766f7/src/librustc/middle/resolve_lifetime.rs#L823)).
- Once a name is in scope, [`resolve_lifetime_ref()`](https://github.com/rust-lang/rust/blob/3cf28f3002470f61a471c69b869e4f55ae1766f7/src/librustc/middle/resolve_lifetime.rs#L866) 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.
- 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](https://forge.rust-lang.org/rustc-bug-fix-procedure.html) -- we can skip the "future compatibility" parts here.)