@@ -977,6 +977,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
977977 can_suggest_clone
978978 }
979979
980+ pub ( crate ) fn suggest_cloning (
981+ & self ,
982+ err : & mut Diag < ' _ > ,
983+ ty : Ty < ' tcx > ,
984+ expr : & hir:: Expr < ' _ > ,
985+ span : Span ,
986+ ) {
987+ if let Some ( clone_trait_def) = self . infcx . tcx . lang_items ( ) . clone_trait ( )
988+ && self
989+ . infcx
990+ . type_implements_trait ( clone_trait_def, [ ty] , self . param_env )
991+ . must_apply_modulo_regions ( )
992+ {
993+ self . suggest_cloning_inner ( err, ty, expr, span) ;
994+ }
995+ }
996+
980997 pub ( crate ) fn clone_on_reference ( & self , expr : & hir:: Expr < ' _ > ) -> Option < Span > {
981998 let typeck_results = self . infcx . tcx . typeck ( self . mir_def_id ( ) ) ;
982999 if let hir:: ExprKind :: MethodCall ( segment, rcvr, args, span) = expr. kind
@@ -992,7 +1009,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
9921009 }
9931010 }
9941011
995- fn suggest_cloning ( & self , err : & mut Diag < ' _ > , ty : Ty < ' tcx > , expr : & hir:: Expr < ' _ > , span : Span ) {
1012+ fn suggest_cloning_inner (
1013+ & self ,
1014+ err : & mut Diag < ' _ > ,
1015+ ty : Ty < ' tcx > ,
1016+ expr : & hir:: Expr < ' _ > ,
1017+ span : Span ,
1018+ ) {
9961019 let tcx = self . infcx . tcx ;
9971020 // Try to find predicates on *generic params* that would allow copying `ty`
9981021 let suggestion =
@@ -1126,6 +1149,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11261149 None ,
11271150 ) ;
11281151 self . suggest_copy_for_type_in_cloned_ref ( & mut err, place) ;
1152+ let typeck_results = self . infcx . tcx . typeck ( self . mir_def_id ( ) ) ;
1153+ if let Some ( expr) = self . find_expr ( borrow_span)
1154+ && let Some ( ty) = typeck_results. node_type_opt ( expr. hir_id )
1155+ {
1156+ self . suggest_cloning ( & mut err, ty, expr, borrow_span) ;
1157+ }
11291158 self . buffer_error ( err) ;
11301159 }
11311160
@@ -1543,22 +1572,32 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
15431572 }
15441573 }
15451574 for ty in types_to_constrain {
1546- self . suggest_adding_bounds ( err, ty, clone, body. span ) ;
1547- if let ty:: Adt ( ..) = ty. kind ( ) {
1548- // The type doesn't implement Clone.
1549- let trait_ref = ty:: Binder :: dummy ( ty:: TraitRef :: new ( self . infcx . tcx , clone, [ ty] ) ) ;
1550- let obligation = Obligation :: new (
1551- self . infcx . tcx ,
1552- ObligationCause :: dummy ( ) ,
1553- self . param_env ,
1554- trait_ref,
1555- ) ;
1556- self . infcx . err_ctxt ( ) . suggest_derive (
1557- & obligation,
1558- err,
1559- trait_ref. to_predicate ( self . infcx . tcx ) ,
1560- ) ;
1561- }
1575+ self . suggest_adding_bounds_or_derive ( err, ty, clone, body. span ) ;
1576+ }
1577+ }
1578+
1579+ pub ( crate ) fn suggest_adding_bounds_or_derive (
1580+ & self ,
1581+ err : & mut Diag < ' _ > ,
1582+ ty : Ty < ' tcx > ,
1583+ def_id : DefId ,
1584+ span : Span ,
1585+ ) {
1586+ self . suggest_adding_bounds ( err, ty, def_id, span) ;
1587+ if let ty:: Adt ( ..) = ty. kind ( ) {
1588+ // The type doesn't implement DefId.
1589+ let trait_ref = ty:: Binder :: dummy ( ty:: TraitRef :: new ( self . infcx . tcx , def_id, [ ty] ) ) ;
1590+ let obligation = Obligation :: new (
1591+ self . infcx . tcx ,
1592+ ObligationCause :: dummy ( ) ,
1593+ self . param_env ,
1594+ trait_ref,
1595+ ) ;
1596+ self . infcx . err_ctxt ( ) . suggest_derive (
1597+ & obligation,
1598+ err,
1599+ trait_ref. to_predicate ( self . infcx . tcx ) ,
1600+ ) ;
15621601 }
15631602 }
15641603
0 commit comments