@@ -6,6 +6,7 @@ use rustc_errors::{Applicability, Diagnostic};
6
6
use rustc_hir as hir;
7
7
use rustc_hir:: def:: { CtorKind , Namespace } ;
8
8
use rustc_hir:: GeneratorKind ;
9
+ use rustc_hir_analysis:: hir_ty_to_ty;
9
10
use rustc_infer:: infer:: TyCtxtInferExt ;
10
11
use rustc_middle:: mir:: tcx:: PlaceTy ;
11
12
use rustc_middle:: mir:: {
@@ -1066,18 +1067,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1066
1067
}
1067
1068
CallKind :: Normal { self_arg, desugaring, method_did } => {
1068
1069
let self_arg = self_arg. unwrap ( ) ;
1070
+ let tcx = self . infcx . tcx ;
1069
1071
if let Some ( ( CallDesugaringKind :: ForLoopIntoIter , _) ) = desugaring {
1070
- let ty = moved_place. ty ( self . body , self . infcx . tcx ) . ty ;
1071
- let suggest = match self . infcx . tcx . get_diagnostic_item ( sym:: IntoIterator ) {
1072
+ let ty = moved_place. ty ( self . body , tcx) . ty ;
1073
+ let suggest = match tcx. get_diagnostic_item ( sym:: IntoIterator ) {
1072
1074
Some ( def_id) => {
1073
1075
let infcx = self . infcx . tcx . infer_ctxt ( ) . build ( ) ;
1074
1076
type_known_to_meet_bound_modulo_regions (
1075
1077
& infcx,
1076
1078
self . param_env ,
1077
- infcx. tcx . mk_imm_ref (
1078
- infcx. tcx . lifetimes . re_erased ,
1079
- infcx. tcx . erase_regions ( ty) ,
1080
- ) ,
1079
+ tcx. mk_imm_ref ( tcx. lifetimes . re_erased , tcx. erase_regions ( ty) ) ,
1081
1080
def_id,
1082
1081
DUMMY_SP ,
1083
1082
)
@@ -1133,8 +1132,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1133
1132
place_name, partially_str, loop_message
1134
1133
) ,
1135
1134
) ;
1136
- if let ty:: Adt ( def , .. )
1137
- = moved_place . ty ( self . body , self . infcx . tcx ) . ty . kind ( )
1135
+ let ty = moved_place . ty ( self . body , self . infcx . tcx ) . ty ;
1136
+ if let ty :: Adt ( def , .. ) = ty. kind ( )
1138
1137
&& Some ( def. did ( ) ) == self . infcx . tcx . lang_items ( ) . pin_type ( )
1139
1138
{
1140
1139
err. span_suggestion_verbose (
@@ -1144,8 +1143,34 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1144
1143
Applicability :: MaybeIncorrect ,
1145
1144
) ;
1146
1145
}
1146
+ if let Some ( clone_trait) = tcx. lang_items ( ) . clone_trait ( ) {
1147
+ // We can't use `predicate_may_hold` or `can_eq` without ICEs in
1148
+ // borrowck because of the inference context, so we do a poor-man's
1149
+ // version here.
1150
+ for impl_def_id in tcx. all_impls ( clone_trait) {
1151
+ if let Some ( def_id) = impl_def_id. as_local ( )
1152
+ && let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id)
1153
+ && let hir:: Node :: Item ( hir:: Item {
1154
+ kind : hir:: ItemKind :: Impl ( hir:: Impl {
1155
+ self_ty,
1156
+ ..
1157
+ } ) ,
1158
+ ..
1159
+ } ) = tcx. hir ( ) . get ( hir_id)
1160
+ {
1161
+ if ty == hir_ty_to_ty ( tcx, self_ty) {
1162
+ err. span_suggestion_verbose (
1163
+ fn_call_span. shrink_to_lo ( ) ,
1164
+ "you can `clone` the value and consume it, but this \
1165
+ might not be your desired behavior",
1166
+ "clone()." . to_string ( ) ,
1167
+ Applicability :: MaybeIncorrect ,
1168
+ ) ;
1169
+ }
1170
+ }
1171
+ }
1172
+ }
1147
1173
}
1148
- let tcx = self . infcx . tcx ;
1149
1174
// Avoid pointing to the same function in multiple different
1150
1175
// error messages.
1151
1176
if span != DUMMY_SP && self . fn_self_span_reported . insert ( self_arg. span ) {
0 commit comments