@@ -205,16 +205,25 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
205205                    is_loop_move = true ; 
206206                } 
207207
208+                 let  mut  has_suggest_reborrow = false ; 
208209                if  !seen_spans. contains ( & move_span)  { 
209210                    if  !closure { 
210-                         self . suggest_ref_or_clone ( mpi,  & mut  err,  & mut  in_pattern,  move_spans) ; 
211+                         self . suggest_ref_or_clone ( 
212+                             mpi, 
213+                             & mut  err, 
214+                             & mut  in_pattern, 
215+                             move_spans, 
216+                             moved_place. as_ref ( ) , 
217+                             & mut  has_suggest_reborrow, 
218+                         ) ; 
211219                    } 
212220
213221                    let  msg_opt = CapturedMessageOpt  { 
214222                        is_partial_move, 
215223                        is_loop_message, 
216224                        is_move_msg, 
217225                        is_loop_move, 
226+                         has_suggest_reborrow, 
218227                        maybe_reinitialized_locations_is_empty :  maybe_reinitialized_locations
219228                            . is_empty ( ) , 
220229                    } ; 
@@ -259,17 +268,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
259268            if  is_loop_move &  !in_pattern && !matches ! ( use_spans,  UseSpans :: ClosureUse  {  .. } )  { 
260269                if  let  ty:: Ref ( _,  _,  hir:: Mutability :: Mut )  = ty. kind ( )  { 
261270                    // We have a `&mut` ref, we need to reborrow on each iteration (#62112). 
262-                     err. span_suggestion_verbose ( 
263-                         span. shrink_to_lo ( ) , 
264-                         format ! ( 
265-                             "consider creating a fresh reborrow of {} here" , 
266-                             self . describe_place( moved_place) 
267-                                 . map( |n| format!( "`{n}`" ) ) 
268-                                 . unwrap_or_else( || "the mutable reference" . to_string( ) ) , 
269-                         ) , 
270-                         "&mut *" , 
271-                         Applicability :: MachineApplicable , 
272-                     ) ; 
271+                     self . suggest_reborrow ( & mut  err,  span,  moved_place) ; 
273272                } 
274273            } 
275274
@@ -346,6 +345,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
346345        err :  & mut  Diag < ' infcx > , 
347346        in_pattern :  & mut  bool , 
348347        move_spans :  UseSpans < ' tcx > , 
348+         moved_place :  PlaceRef < ' tcx > , 
349+         has_suggest_reborrow :  & mut  bool , 
349350    )  { 
350351        let  move_span = match  move_spans { 
351352            UseSpans :: ClosureUse  {  capture_kind_span,  .. }  => capture_kind_span, 
@@ -435,20 +436,44 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
435436                let  parent = self . infcx . tcx . parent_hir_node ( expr. hir_id ) ; 
436437                let  ( def_id,  args,  offset)  = if  let  hir:: Node :: Expr ( parent_expr)  = parent
437438                    && let  hir:: ExprKind :: MethodCall ( _,  _,  args,  _)  = parent_expr. kind 
438-                     && let  Some ( def_id)  = typeck. type_dependent_def_id ( parent_expr. hir_id ) 
439439                { 
440-                     ( def_id . as_local ( ) ,  args,  1 ) 
440+                     ( typeck . type_dependent_def_id ( parent_expr . hir_id ) ,  args,  1 ) 
441441                }  else  if  let  hir:: Node :: Expr ( parent_expr)  = parent
442442                    && let  hir:: ExprKind :: Call ( call,  args)  = parent_expr. kind 
443443                    && let  ty:: FnDef ( def_id,  _)  = typeck. node_type ( call. hir_id ) . kind ( ) 
444444                { 
445-                     ( def_id . as_local ( ) ,  args,  0 ) 
445+                     ( Some ( * def_id ) ,  args,  0 ) 
446446                }  else  { 
447447                    ( None ,  & [ ] [ ..] ,  0 ) 
448448                } ; 
449+ 
450+                 // If the moved value is a mut reference, it is used in a 
451+                 // generic function and it's type is a generic param, it can be 
452+                 // reborrowed to avoid moving. 
453+                 // for example: 
454+                 // struct Y(u32); 
455+                 // x's type is '& mut Y' and it is used in `fn generic<T>(x: T) {}`. 
456+                 if  let  Some ( def_id)  = def_id
457+                     && self . infcx . tcx . def_kind ( def_id) . is_fn_like ( ) 
458+                     && let  Some ( pos)  = args. iter ( ) . position ( |arg| arg. hir_id  == expr. hir_id ) 
459+                     && let  ty:: Param ( _)  =
460+                         self . infcx . tcx . fn_sig ( def_id) . skip_binder ( ) . skip_binder ( ) . inputs ( ) 
461+                             [ pos + offset] 
462+                             . kind ( ) 
463+                 { 
464+                     let  place = & self . move_data . move_paths [ mpi] . place ; 
465+                     let  ty = place. ty ( self . body ,  self . infcx . tcx ) . ty ; 
466+                     if  let  ty:: Ref ( _,  _,  hir:: Mutability :: Mut )  = ty. kind ( )  { 
467+                         * has_suggest_reborrow = true ; 
468+                         self . suggest_reborrow ( err,  expr. span ,  moved_place) ; 
469+                         return ; 
470+                     } 
471+                 } 
472+ 
449473                let  mut  can_suggest_clone = true ; 
450474                if  let  Some ( def_id)  = def_id
451-                     && let  node = self . infcx . tcx . hir_node_by_def_id ( def_id) 
475+                     && let  Some ( local_def_id)  = def_id. as_local ( ) 
476+                     && let  node = self . infcx . tcx . hir_node_by_def_id ( local_def_id) 
452477                    && let  Some ( fn_sig)  = node. fn_sig ( ) 
453478                    && let  Some ( ident)  = node. ident ( ) 
454479                    && let  Some ( pos)  = args. iter ( ) . position ( |arg| arg. hir_id  == expr. hir_id ) 
@@ -622,6 +647,25 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
622647        } 
623648    } 
624649
650+     pub  fn  suggest_reborrow ( 
651+         & self , 
652+         err :  & mut  Diag < ' infcx > , 
653+         span :  Span , 
654+         moved_place :  PlaceRef < ' tcx > , 
655+     )  { 
656+         err. span_suggestion_verbose ( 
657+             span. shrink_to_lo ( ) , 
658+             format ! ( 
659+                 "consider creating a fresh reborrow of {} here" , 
660+                 self . describe_place( moved_place) 
661+                     . map( |n| format!( "`{n}`" ) ) 
662+                     . unwrap_or_else( || "the mutable reference" . to_string( ) ) , 
663+             ) , 
664+             "&mut *" , 
665+             Applicability :: MachineApplicable , 
666+         ) ; 
667+     } 
668+ 
625669    fn  report_use_of_uninitialized ( 
626670        & self , 
627671        mpi :  MovePathIndex , 
0 commit comments