@@ -747,6 +747,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
747747 true
748748 }
749749
750+ pub ( crate ) fn suggest_cloning (
751+ & self ,
752+ err : & mut Diag < ' _ > ,
753+ ty : Ty < ' tcx > ,
754+ expr : & hir:: Expr < ' _ > ,
755+ span : Span ,
756+ ) {
757+ if let Some ( clone_trait_def) = self . infcx . tcx . lang_items ( ) . clone_trait ( )
758+ && self
759+ . infcx
760+ . type_implements_trait ( clone_trait_def, [ ty] , self . param_env )
761+ . must_apply_modulo_regions ( )
762+ {
763+ self . suggest_cloning_inner ( err, ty, expr, span) ;
764+ }
765+ }
766+
750767 pub ( crate ) fn clone_on_reference ( & self , expr : & hir:: Expr < ' _ > ) -> Option < Span > {
751768 let typeck_results = self . infcx . tcx . typeck ( self . mir_def_id ( ) ) ;
752769 if let hir:: ExprKind :: MethodCall ( segment, rcvr, args, span) = expr. kind
@@ -762,7 +779,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
762779 }
763780 }
764781
765- fn suggest_cloning ( & self , err : & mut Diag < ' _ > , ty : Ty < ' tcx > , expr : & hir:: Expr < ' _ > , span : Span ) {
782+ fn suggest_cloning_inner (
783+ & self ,
784+ err : & mut Diag < ' _ > ,
785+ ty : Ty < ' tcx > ,
786+ expr : & hir:: Expr < ' _ > ,
787+ span : Span ,
788+ ) {
766789 let tcx = self . infcx . tcx ;
767790 // Try to find predicates on *generic params* that would allow copying `ty`
768791 let suggestion =
@@ -896,6 +919,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
896919 None ,
897920 ) ;
898921 self . suggest_copy_for_type_in_cloned_ref ( & mut err, place) ;
922+ let typeck_results = self . infcx . tcx . typeck ( self . mir_def_id ( ) ) ;
923+ if let Some ( expr) = self . find_expr ( borrow_span)
924+ && let Some ( ty) = typeck_results. node_type_opt ( expr. hir_id )
925+ {
926+ self . suggest_cloning ( & mut err, ty, expr, borrow_span) ;
927+ }
899928 self . buffer_error ( err) ;
900929 }
901930
@@ -1313,22 +1342,32 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
13131342 }
13141343 }
13151344 for ty in types_to_constrain {
1316- self . suggest_adding_bounds ( err, ty, clone, body. span ) ;
1317- if let ty:: Adt ( ..) = ty. kind ( ) {
1318- // The type doesn't implement Clone.
1319- let trait_ref = ty:: Binder :: dummy ( ty:: TraitRef :: new ( self . infcx . tcx , clone, [ ty] ) ) ;
1320- let obligation = Obligation :: new (
1321- self . infcx . tcx ,
1322- ObligationCause :: dummy ( ) ,
1323- self . param_env ,
1324- trait_ref,
1325- ) ;
1326- self . infcx . err_ctxt ( ) . suggest_derive (
1327- & obligation,
1328- err,
1329- trait_ref. to_predicate ( self . infcx . tcx ) ,
1330- ) ;
1331- }
1345+ self . suggest_adding_bounds_or_derive ( err, ty, clone, body. span ) ;
1346+ }
1347+ }
1348+
1349+ pub ( crate ) fn suggest_adding_bounds_or_derive (
1350+ & self ,
1351+ err : & mut Diag < ' _ > ,
1352+ ty : Ty < ' tcx > ,
1353+ def_id : DefId ,
1354+ span : Span ,
1355+ ) {
1356+ self . suggest_adding_bounds ( err, ty, def_id, span) ;
1357+ if let ty:: Adt ( ..) = ty. kind ( ) {
1358+ // The type doesn't implement DefId.
1359+ let trait_ref = ty:: Binder :: dummy ( ty:: TraitRef :: new ( self . infcx . tcx , def_id, [ ty] ) ) ;
1360+ let obligation = Obligation :: new (
1361+ self . infcx . tcx ,
1362+ ObligationCause :: dummy ( ) ,
1363+ self . param_env ,
1364+ trait_ref,
1365+ ) ;
1366+ self . infcx . err_ctxt ( ) . suggest_derive (
1367+ & obligation,
1368+ err,
1369+ trait_ref. to_predicate ( self . infcx . tcx ) ,
1370+ ) ;
13321371 }
13331372 }
13341373
0 commit comments