@@ -10,7 +10,7 @@ use crate::infer::InferCtxt;
10
10
use crate :: traits:: { NormalizeExt , ObligationCtxt } ;
11
11
12
12
use hir:: def:: CtorOf ;
13
- use hir:: HirId ;
13
+ use hir:: { Expr , HirId } ;
14
14
use rustc_data_structures:: fx:: FxHashSet ;
15
15
use rustc_data_structures:: stack:: ensure_sufficient_stack;
16
16
use rustc_errors:: {
@@ -206,6 +206,13 @@ pub trait TypeErrCtxtExt<'tcx> {
206
206
trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
207
207
) ;
208
208
209
+ fn suggest_add_clone_to_arg (
210
+ & self ,
211
+ obligation : & PredicateObligation < ' tcx > ,
212
+ err : & mut Diagnostic ,
213
+ trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
214
+ ) -> bool ;
215
+
209
216
fn suggest_add_reference_to_arg (
210
217
& self ,
211
218
obligation : & PredicateObligation < ' tcx > ,
@@ -1102,6 +1109,55 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1102
1109
}
1103
1110
}
1104
1111
1112
+ fn suggest_add_clone_to_arg (
1113
+ & self ,
1114
+ obligation : & PredicateObligation < ' tcx > ,
1115
+ err : & mut Diagnostic ,
1116
+ trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
1117
+ ) -> bool {
1118
+ let self_ty = self . resolve_vars_if_possible ( trait_pred. self_ty ( ) ) ;
1119
+ let ty = self . tcx . erase_late_bound_regions ( self_ty) ;
1120
+ let owner = self . tcx . hir ( ) . get_parent_item ( obligation. cause . body_id ) ;
1121
+ let Some ( generics) = self . tcx . hir ( ) . get_generics ( owner. def_id ) else { return false } ;
1122
+ let ty:: Ref ( _, inner_ty, hir:: Mutability :: Not ) = ty. kind ( ) else { return false } ;
1123
+ let ty:: Param ( param) = inner_ty. kind ( ) else { return false } ;
1124
+ let ObligationCauseCode :: FunctionArgumentObligation { arg_hir_id, .. } = obligation. cause . code ( ) else { return false } ;
1125
+ let arg_node = self . tcx . hir ( ) . get ( * arg_hir_id) ;
1126
+ let Node :: Expr ( Expr { kind : hir:: ExprKind :: Path ( _) , ..} ) = arg_node else { return false } ;
1127
+
1128
+ let clone_trait = self . tcx . require_lang_item ( LangItem :: Clone , None ) ;
1129
+ let has_clone = |ty| {
1130
+ self . type_implements_trait ( clone_trait, [ ty] , obligation. param_env )
1131
+ . must_apply_modulo_regions ( )
1132
+ } ;
1133
+
1134
+ let new_obligation = self . mk_trait_obligation_with_new_self_ty (
1135
+ obligation. param_env ,
1136
+ trait_pred. map_bound ( |trait_pred| ( trait_pred, * inner_ty) ) ,
1137
+ ) ;
1138
+
1139
+ if self . predicate_may_hold ( & new_obligation) && has_clone ( ty) {
1140
+ if !has_clone ( param. to_ty ( self . tcx ) ) {
1141
+ suggest_constraining_type_param (
1142
+ self . tcx ,
1143
+ generics,
1144
+ err,
1145
+ param. name . as_str ( ) ,
1146
+ "Clone" ,
1147
+ Some ( clone_trait) ,
1148
+ ) ;
1149
+ }
1150
+ err. span_suggestion_verbose (
1151
+ obligation. cause . span . shrink_to_hi ( ) ,
1152
+ "consider using clone here" ,
1153
+ ".clone()" . to_string ( ) ,
1154
+ Applicability :: MaybeIncorrect ,
1155
+ ) ;
1156
+ return true ;
1157
+ }
1158
+ false
1159
+ }
1160
+
1105
1161
fn suggest_add_reference_to_arg (
1106
1162
& self ,
1107
1163
obligation : & PredicateObligation < ' tcx > ,
0 commit comments