Rollup merge of #122174 - notriddle:master, r=TaKO8Ki
diagnostics: suggest `Clone` bounds when noop `clone()` Fixes #121524
This commit is contained in:
commit
e66c7e479c
3 changed files with 88 additions and 10 deletions
|
@ -987,10 +987,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
else {
|
||||
return false;
|
||||
};
|
||||
let arg_node = self.tcx.hir_node(*arg_hir_id);
|
||||
let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None);
|
||||
let has_clone = |ty| {
|
||||
|
@ -998,6 +994,39 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
.must_apply_modulo_regions()
|
||||
};
|
||||
|
||||
let existing_clone_call = match self.tcx.hir_node(*arg_hir_id) {
|
||||
// It's just a variable. Propose cloning it.
|
||||
Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) => None,
|
||||
// It's already a call to `clone()`. We might be able to suggest
|
||||
// adding a `+ Clone` bound, though.
|
||||
Node::Expr(Expr {
|
||||
kind:
|
||||
hir::ExprKind::MethodCall(
|
||||
hir::PathSegment { ident, .. },
|
||||
_receiver,
|
||||
&[],
|
||||
call_span,
|
||||
),
|
||||
hir_id,
|
||||
..
|
||||
}) if ident.name == sym::clone
|
||||
&& !call_span.from_expansion()
|
||||
&& !has_clone(*inner_ty) =>
|
||||
{
|
||||
// We only care about method calls corresponding to the real `Clone` trait.
|
||||
let Some(typeck_results) = self.typeck_results.as_ref() else { return false };
|
||||
let Some((DefKind::AssocFn, did)) = typeck_results.type_dependent_def(*hir_id)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
if self.tcx.trait_of_item(did) != Some(clone_trait) {
|
||||
return false;
|
||||
}
|
||||
Some(ident.span)
|
||||
}
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||
obligation.param_env,
|
||||
trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)),
|
||||
|
@ -1015,12 +1044,23 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
None,
|
||||
);
|
||||
}
|
||||
err.span_suggestion_verbose(
|
||||
obligation.cause.span.shrink_to_hi(),
|
||||
"consider using clone here",
|
||||
".clone()".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
if let Some(existing_clone_call) = existing_clone_call {
|
||||
err.span_note(
|
||||
existing_clone_call,
|
||||
format!(
|
||||
"this `clone()` copies the reference, \
|
||||
which does not do anything, \
|
||||
because `{inner_ty}` does not implement `Clone`"
|
||||
),
|
||||
);
|
||||
} else {
|
||||
err.span_suggestion_verbose(
|
||||
obligation.cause.span.shrink_to_hi(),
|
||||
"consider using clone here",
|
||||
".clone()".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
false
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue