@@ -6,6 +6,7 @@ use rustc_errors::{Applicability, Diagnostic};
66use rustc_hir as hir;
77use rustc_hir:: def:: { CtorKind , Namespace } ;
88use rustc_hir:: GeneratorKind ;
9+ use rustc_hir_analysis:: hir_ty_to_ty;
910use rustc_infer:: infer:: TyCtxtInferExt ;
1011use rustc_middle:: mir:: tcx:: PlaceTy ;
1112use rustc_middle:: mir:: {
@@ -1066,18 +1067,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
10661067 }
10671068 CallKind :: Normal { self_arg, desugaring, method_did } => {
10681069 let self_arg = self_arg. unwrap ( ) ;
1070+ let tcx = self . infcx . tcx ;
10691071 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 ) {
10721074 Some ( def_id) => {
10731075 let infcx = self . infcx . tcx . infer_ctxt ( ) . build ( ) ;
10741076 type_known_to_meet_bound_modulo_regions (
10751077 & infcx,
10761078 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) ) ,
10811080 def_id,
10821081 DUMMY_SP ,
10831082 )
@@ -1133,8 +1132,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11331132 place_name, partially_str, loop_message
11341133 ) ,
11351134 ) ;
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 ( )
11381137 && Some ( def. did ( ) ) == self . infcx . tcx . lang_items ( ) . pin_type ( )
11391138 {
11401139 err. span_suggestion_verbose (
@@ -1144,8 +1143,34 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11441143 Applicability :: MaybeIncorrect ,
11451144 ) ;
11461145 }
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+ }
11471173 }
1148- let tcx = self . infcx . tcx ;
11491174 // Avoid pointing to the same function in multiple different
11501175 // error messages.
11511176 if span != DUMMY_SP && self . fn_self_span_reported . insert ( self_arg. span ) {
0 commit comments