@@ -987,6 +987,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
987987 can_suggest_clone
988988 }
989989
990+ pub ( crate ) fn suggest_cloning (
991+ & self ,
992+ err : & mut Diag < ' _ > ,
993+ ty : Ty < ' tcx > ,
994+ expr : & hir:: Expr < ' _ > ,
995+ span : Span ,
996+ ) {
997+ if let Some ( clone_trait_def) = self . infcx . tcx . lang_items ( ) . clone_trait ( )
998+ && self
999+ . infcx
1000+ . type_implements_trait ( clone_trait_def, [ ty] , self . param_env )
1001+ . must_apply_modulo_regions ( )
1002+ {
1003+ self . suggest_cloning_inner ( err, ty, expr, span) ;
1004+ }
1005+ }
1006+
9901007 pub ( crate ) fn clone_on_reference ( & self , expr : & hir:: Expr < ' _ > ) -> Option < Span > {
9911008 let typeck_results = self . infcx . tcx . typeck ( self . mir_def_id ( ) ) ;
9921009 if let hir:: ExprKind :: MethodCall ( segment, rcvr, args, span) = expr. kind
@@ -1002,7 +1019,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
10021019 }
10031020 }
10041021
1005- fn suggest_cloning ( & self , err : & mut Diag < ' _ > , ty : Ty < ' tcx > , expr : & hir:: Expr < ' _ > , span : Span ) {
1022+ fn suggest_cloning_inner (
1023+ & self ,
1024+ err : & mut Diag < ' _ > ,
1025+ ty : Ty < ' tcx > ,
1026+ expr : & hir:: Expr < ' _ > ,
1027+ span : Span ,
1028+ ) {
10061029 let tcx = self . infcx . tcx ;
10071030 // Try to find predicates on *generic params* that would allow copying `ty`
10081031 let suggestion =
@@ -1136,6 +1159,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11361159 None ,
11371160 ) ;
11381161 self . suggest_copy_for_type_in_cloned_ref ( & mut err, place) ;
1162+ let typeck_results = self . infcx . tcx . typeck ( self . mir_def_id ( ) ) ;
1163+ if let Some ( expr) = self . find_expr ( borrow_span)
1164+ && let Some ( ty) = typeck_results. node_type_opt ( expr. hir_id )
1165+ {
1166+ self . suggest_cloning ( & mut err, ty, expr, borrow_span) ;
1167+ }
11391168 self . buffer_error ( err) ;
11401169 }
11411170
@@ -1553,22 +1582,32 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
15531582 }
15541583 }
15551584 for ty in types_to_constrain {
1556- self . suggest_adding_bounds ( err, ty, clone, body. span ) ;
1557- if let ty:: Adt ( ..) = ty. kind ( ) {
1558- // The type doesn't implement Clone.
1559- let trait_ref = ty:: Binder :: dummy ( ty:: TraitRef :: new ( self . infcx . tcx , clone, [ ty] ) ) ;
1560- let obligation = Obligation :: new (
1561- self . infcx . tcx ,
1562- ObligationCause :: dummy ( ) ,
1563- self . param_env ,
1564- trait_ref,
1565- ) ;
1566- self . infcx . err_ctxt ( ) . suggest_derive (
1567- & obligation,
1568- err,
1569- trait_ref. to_predicate ( self . infcx . tcx ) ,
1570- ) ;
1571- }
1585+ self . suggest_adding_bounds_or_derive ( err, ty, clone, body. span ) ;
1586+ }
1587+ }
1588+
1589+ pub ( crate ) fn suggest_adding_bounds_or_derive (
1590+ & self ,
1591+ err : & mut Diag < ' _ > ,
1592+ ty : Ty < ' tcx > ,
1593+ def_id : DefId ,
1594+ span : Span ,
1595+ ) {
1596+ self . suggest_adding_bounds ( err, ty, def_id, span) ;
1597+ if let ty:: Adt ( ..) = ty. kind ( ) {
1598+ // The type doesn't implement DefId.
1599+ let trait_ref = ty:: Binder :: dummy ( ty:: TraitRef :: new ( self . infcx . tcx , def_id, [ ty] ) ) ;
1600+ let obligation = Obligation :: new (
1601+ self . infcx . tcx ,
1602+ ObligationCause :: dummy ( ) ,
1603+ self . param_env ,
1604+ trait_ref,
1605+ ) ;
1606+ self . infcx . err_ctxt ( ) . suggest_derive (
1607+ & obligation,
1608+ err,
1609+ trait_ref. to_predicate ( self . infcx . tcx ) ,
1610+ ) ;
15721611 }
15731612 }
15741613
0 commit comments