Mention when type parameter could be Clone
``` error[E0382]: use of moved value: `t` --> $DIR/use_of_moved_value_copy_suggestions.rs:7:9 | LL | fn duplicate_t<T>(t: T) -> (T, T) { | - move occurs because `t` has type `T`, which does not implement the `Copy` trait ... LL | (t, t) | - ^ value used here after move | | | value moved here | help: if `T` implemented `Clone`, you could clone the value --> $DIR/use_of_moved_value_copy_suggestions.rs:4:16 | LL | fn duplicate_t<T>(t: T) -> (T, T) { | ^ consider constraining this type parameter with `Clone` ... LL | (t, t) | - you could clone this value help: consider restricting type parameter `T` | LL | fn duplicate_t<T: Copy>(t: T) -> (T, T) { | ++++++ ``` The `help` is new. On ADTs, we also extend the output with span labels: ``` error[E0507]: cannot move out of static item `FOO` --> $DIR/issue-17718-static-move.rs:6:14 | LL | let _a = FOO; | ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait | note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/issue-17718-static-move.rs:1:1 | LL | struct Foo; | ^^^^^^^^^^ consider implementing `Clone` for this type ... LL | let _a = FOO; | --- you could clone this value help: consider borrowing here | LL | let _a = &FOO; | + ```
This commit is contained in:
parent
4aba2c55e6
commit
d68f2a6b71
51 changed files with 640 additions and 86 deletions
|
@ -347,7 +347,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
mpi: MovePathIndex,
|
||||
err: &mut Diag<'tcx>,
|
||||
in_pattern: &mut bool,
|
||||
move_spans: UseSpans<'_>,
|
||||
move_spans: UseSpans<'tcx>,
|
||||
) {
|
||||
let move_span = match move_spans {
|
||||
UseSpans::ClosureUse { capture_kind_span, .. } => capture_kind_span,
|
||||
|
@ -491,11 +491,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
..
|
||||
} = move_spans
|
||||
{
|
||||
self.suggest_cloning(err, ty, expr, None);
|
||||
self.suggest_cloning(err, ty, expr, None, Some(move_spans));
|
||||
} else if self.suggest_hoisting_call_outside_loop(err, expr) {
|
||||
// The place where the the type moves would be misleading to suggest clone.
|
||||
// #121466
|
||||
self.suggest_cloning(err, ty, expr, None);
|
||||
self.suggest_cloning(err, ty, expr, None, Some(move_spans));
|
||||
}
|
||||
}
|
||||
if let Some(pat) = finder.pat {
|
||||
|
@ -1085,6 +1085,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
ty: Ty<'tcx>,
|
||||
mut expr: &'cx hir::Expr<'cx>,
|
||||
mut other_expr: Option<&'cx hir::Expr<'cx>>,
|
||||
use_spans: Option<UseSpans<'tcx>>,
|
||||
) {
|
||||
if let hir::ExprKind::Struct(_, _, Some(_)) = expr.kind {
|
||||
// We have `S { foo: val, ..base }`. In `check_aggregate_rvalue` we have a single
|
||||
|
@ -1197,8 +1198,44 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
.all(|field| self.implements_clone(field.ty(self.infcx.tcx, args)))
|
||||
})
|
||||
{
|
||||
let ty_span = self.infcx.tcx.def_span(def.did());
|
||||
let mut span: MultiSpan = ty_span.into();
|
||||
span.push_span_label(ty_span, "consider implementing `Clone` for this type");
|
||||
span.push_span_label(expr.span, "you could clone this value");
|
||||
err.span_note(
|
||||
self.infcx.tcx.def_span(def.did()),
|
||||
span,
|
||||
format!("if `{ty}` implemented `Clone`, you could clone the value"),
|
||||
);
|
||||
} else if let ty::Param(param) = ty.kind()
|
||||
&& let Some(_clone_trait_def) = self.infcx.tcx.lang_items().clone_trait()
|
||||
&& let generics = self.infcx.tcx.generics_of(self.mir_def_id())
|
||||
&& let generic_param = generics.type_param(*param, self.infcx.tcx)
|
||||
&& let param_span = self.infcx.tcx.def_span(generic_param.def_id)
|
||||
&& if let Some(UseSpans::FnSelfUse { kind, .. }) = use_spans
|
||||
&& let CallKind::FnCall { fn_trait_id, self_ty } = kind
|
||||
&& let ty::Param(_) = self_ty.kind()
|
||||
&& ty == self_ty
|
||||
&& [
|
||||
self.infcx.tcx.lang_items().fn_once_trait(),
|
||||
self.infcx.tcx.lang_items().fn_mut_trait(),
|
||||
self.infcx.tcx.lang_items().fn_trait(),
|
||||
]
|
||||
.contains(&Some(fn_trait_id))
|
||||
{
|
||||
// Do not suggest `F: FnOnce() + Clone`.
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
{
|
||||
let mut span: MultiSpan = param_span.into();
|
||||
span.push_span_label(
|
||||
param_span,
|
||||
"consider constraining this type parameter with `Clone`",
|
||||
);
|
||||
span.push_span_label(expr.span, "you could clone this value");
|
||||
err.span_help(
|
||||
span,
|
||||
format!("if `{ty}` implemented `Clone`, you could clone the value"),
|
||||
);
|
||||
}
|
||||
|
@ -1403,7 +1440,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if let Some(expr) = self.find_expr(borrow_span)
|
||||
&& let Some(ty) = typeck_results.node_type_opt(expr.hir_id)
|
||||
{
|
||||
self.suggest_cloning(&mut err, ty, expr, self.find_expr(span));
|
||||
self.suggest_cloning(&mut err, ty, expr, self.find_expr(span), Some(move_spans));
|
||||
}
|
||||
self.buffer_error(err);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue