1
Fork 0

Provide suggestion to dereference closure tail if appropriate

When encoutnering a case like

```rust
//@ run-rustfix
use std::collections::HashMap;

fn main() {
    let vs = vec![0, 0, 1, 1, 3, 4, 5, 6, 3, 3, 3];

    let mut counts = HashMap::new();
    for num in vs {
        let count = counts.entry(num).or_insert(0);
        *count += 1;
    }

    let _ = counts.iter().max_by_key(|(_, v)| v);
```
produce the following suggestion
```
error: lifetime may not live long enough
  --> $DIR/return-value-lifetime-error.rs:13:47
   |
LL |     let _ = counts.iter().max_by_key(|(_, v)| v);
   |                                       ------- ^ returning this value requires that `'1` must outlive `'2`
   |                                       |     |
   |                                       |     return type of closure is &'2 &i32
   |                                       has type `&'1 (&i32, &i32)`
   |
help: dereference the return value
   |
LL |     let _ = counts.iter().max_by_key(|(_, v)| **v);
   |                                               ++
```

Fix #50195.
This commit is contained in:
Esteban Küber 2024-03-08 22:59:53 +00:00
parent 76cf07d5df
commit 9de6b70bb6
8 changed files with 298 additions and 5 deletions

View file

@ -1469,27 +1469,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let hir = tcx.hir();
let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
struct FindUselessClone<'hir> {
tcx: TyCtxt<'hir>,
def_id: DefId,
pub clones: Vec<&'hir hir::Expr<'hir>>,
}
impl<'hir> FindUselessClone<'hir> {
pub fn new() -> Self {
Self { clones: vec![] }
pub fn new(tcx: TyCtxt<'hir>, def_id: DefId) -> Self {
Self { tcx, def_id, clones: vec![] }
}
}
impl<'v> Visitor<'v> for FindUselessClone<'v> {
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
// FIXME: use `lookup_method_for_diagnostic`?
if let hir::ExprKind::MethodCall(segment, _rcvr, args, _span) = ex.kind
&& segment.ident.name == sym::clone
&& args.len() == 0
&& let Some(def_id) = self.def_id.as_local()
&& let Some(method) = self.tcx.lookup_method_for_diagnostic((def_id, ex.hir_id))
&& Some(self.tcx.parent(method)) == self.tcx.lang_items().clone_trait()
{
self.clones.push(ex);
}
hir::intravisit::walk_expr(self, ex);
}
}
let mut expr_finder = FindUselessClone::new();
let mut expr_finder = FindUselessClone::new(tcx, self.mir_def_id().into());
let body = hir.body(body_id).value;
expr_finder.visit_expr(body);