Auto merge of #127614 - matthiaskrgr:rollup-8geziwi, r=matthiaskrgr · rust-lang/rust@5e311f9 (original) (raw)
`@@ -445,31 +445,81 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
`
445
445
`} else {
`
446
446
`(None, &[][..], 0)
`
447
447
`};
`
``
448
`+
let mut can_suggest_clone = true;
`
448
449
`if let Some(def_id) = def_id
`
449
450
` && let node = self.infcx.tcx.hir_node_by_def_id(def_id)
`
450
451
` && let Some(fn_sig) = node.fn_sig()
`
451
452
` && let Some(ident) = node.ident()
`
452
453
` && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
`
453
454
` && let Some(arg) = fn_sig.decl.inputs.get(pos + offset)
`
454
455
`{
`
455
``
`-
let mut span: MultiSpan = arg.span.into();
`
456
``
`-
span.push_span_label(
`
457
``
`-
arg.span,
`
458
``
`-
"this parameter takes ownership of the value".to_string(),
`
459
``
`-
);
`
460
``
`-
let descr = match node.fn_kind() {
`
461
``
`-
Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function",
`
462
``
`-
Some(hir::intravisit::FnKind::Method(..)) => "method",
`
463
``
`-
Some(hir::intravisit::FnKind::Closure) => "closure",
`
464
``
`-
};
`
465
``
`-
span.push_span_label(ident.span, format!("in this {descr}"));
`
466
``
`-
err.span_note(
`
467
``
`-
span,
`
468
``
`-
format!(
`
469
``
`` -
"consider changing this parameter type in {descr} {ident}
to borrow \
``
470
``
`-
instead if owning the value isn't necessary",
`
471
``
`-
),
`
472
``
`-
);
`
``
456
`+
let mut is_mut = false;
`
``
457
`+
if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = arg.kind
`
``
458
`+
&& let Res::Def(DefKind::TyParam, param_def_id) = path.res
`
``
459
`+
&& self
`
``
460
`+
.infcx
`
``
461
`+
.tcx
`
``
462
`+
.predicates_of(def_id)
`
``
463
`+
.instantiate_identity(self.infcx.tcx)
`
``
464
`+
.predicates
`
``
465
`+
.into_iter()
`
``
466
`+
.any(|pred| {
`
``
467
`+
if let ty::ClauseKind::Trait(predicate) = pred.kind().skip_binder()
`
``
468
`+
&& [
`
``
469
`+
self.infcx.tcx.get_diagnostic_item(sym::AsRef),
`
``
470
`+
self.infcx.tcx.get_diagnostic_item(sym::AsMut),
`
``
471
`+
self.infcx.tcx.get_diagnostic_item(sym::Borrow),
`
``
472
`+
self.infcx.tcx.get_diagnostic_item(sym::BorrowMut),
`
``
473
`+
]
`
``
474
`+
.contains(&Some(predicate.def_id()))
`
``
475
`+
&& let ty::Param(param) = predicate.self_ty().kind()
`
``
476
`+
&& let generics = self.infcx.tcx.generics_of(def_id)
`
``
477
`+
&& let param = generics.type_param(*param, self.infcx.tcx)
`
``
478
`+
&& param.def_id == param_def_id
`
``
479
`+
{
`
``
480
`+
if [
`
``
481
`+
self.infcx.tcx.get_diagnostic_item(sym::AsMut),
`
``
482
`+
self.infcx.tcx.get_diagnostic_item(sym::BorrowMut),
`
``
483
`+
]
`
``
484
`+
.contains(&Some(predicate.def_id()))
`
``
485
`+
{
`
``
486
`+
is_mut = true;
`
``
487
`+
}
`
``
488
`+
true
`
``
489
`+
} else {
`
``
490
`+
false
`
``
491
`+
}
`
``
492
`+
})
`
``
493
`+
{
`
``
494
`+
// The type of the argument corresponding to the expression that got moved
`
``
495
`` +
// is a type parameter T
, which is has a T: AsRef
obligation.
``
``
496
`+
err.span_suggestion_verbose(
`
``
497
`+
expr.span.shrink_to_lo(),
`
``
498
`+
"borrow the value to avoid moving it",
`
``
499
`+
format!("&{}", if is_mut { "mut " } else { "" }),
`
``
500
`+
Applicability::MachineApplicable,
`
``
501
`+
);
`
``
502
`+
can_suggest_clone = is_mut;
`
``
503
`+
} else {
`
``
504
`+
let mut span: MultiSpan = arg.span.into();
`
``
505
`+
span.push_span_label(
`
``
506
`+
arg.span,
`
``
507
`+
"this parameter takes ownership of the value".to_string(),
`
``
508
`+
);
`
``
509
`+
let descr = match node.fn_kind() {
`
``
510
`+
Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function",
`
``
511
`+
Some(hir::intravisit::FnKind::Method(..)) => "method",
`
``
512
`+
Some(hir::intravisit::FnKind::Closure) => "closure",
`
``
513
`+
};
`
``
514
`+
span.push_span_label(ident.span, format!("in this {descr}"));
`
``
515
`+
err.span_note(
`
``
516
`+
span,
`
``
517
`+
format!(
`
``
518
`` +
"consider changing this parameter type in {descr} {ident}
to \
``
``
519
`+
borrow instead if owning the value isn't necessary",
`
``
520
`+
),
`
``
521
`+
);
`
``
522
`+
}
`
473
523
`}
`
474
524
`let place = &self.move_data.move_paths[mpi].place;
`
475
525
`let ty = place.ty(self.body, self.infcx.tcx).ty;
`
`@@ -487,9 +537,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
`
487
537
`ClosureKind::Coroutine(CoroutineKind::Desugared(_, CoroutineSource::Block)),
`
488
538
` ..
`
489
539
`} = move_spans
`
``
540
`+
&& can_suggest_clone
`
490
541
`{
`
491
542
`self.suggest_cloning(err, ty, expr, None, Some(move_spans));
`
492
``
`-
} else if self.suggest_hoisting_call_outside_loop(err, expr) {
`
``
543
`+
} else if self.suggest_hoisting_call_outside_loop(err, expr) && can_suggest_clone {
`
493
544
`// The place where the type moves would be misleading to suggest clone.
`
494
545
`// #121466
`
495
546
`self.suggest_cloning(err, ty, expr, None, Some(move_spans));
`