@@ -10,7 +10,7 @@ use crate::infer::InferCtxt;
1010use crate :: traits:: { NormalizeExt , ObligationCtxt } ;
1111
1212use hir:: def:: CtorOf ;
13- use hir:: HirId ;
13+ use hir:: { Expr , HirId } ;
1414use rustc_data_structures:: fx:: FxHashSet ;
1515use rustc_data_structures:: stack:: ensure_sufficient_stack;
1616use rustc_errors:: {
@@ -206,6 +206,13 @@ pub trait TypeErrCtxtExt<'tcx> {
206206 trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
207207 ) ;
208208
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+
209216 fn suggest_add_reference_to_arg (
210217 & self ,
211218 obligation : & PredicateObligation < ' tcx > ,
@@ -1102,6 +1109,55 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
11021109 }
11031110 }
11041111
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+
11051161 fn suggest_add_reference_to_arg (
11061162 & self ,
11071163 obligation : & PredicateObligation < ' tcx > ,
0 commit comments