@@ -440,47 +440,46 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
440440 } else {
441441 ( None , & [ ] [ ..] , 0 )
442442 } ;
443+ let ty = place. ty ( self . body , self . infcx . tcx ) . ty ;
443444
444- // If the moved value is a mut reference, it is used in a
445- // generic function and it's type is a generic param, it can be
446- // reborrowed to avoid moving.
447- // for example:
448- // struct Y(u32);
449- // x's type is '& mut Y' and it is used in `fn generic<T>(x: T) {}`.
445+ let mut can_suggest_clone = true ;
450446 if let Some ( def_id) = def_id
451- && self . infcx . tcx . def_kind ( def_id) . is_fn_like ( )
452447 && let Some ( pos) = args. iter ( ) . position ( |arg| arg. hir_id == expr. hir_id )
453- && let Some ( arg) = self
454- . infcx
455- . tcx
456- . fn_sig ( def_id)
457- . skip_binder ( )
458- . skip_binder ( )
459- . inputs ( )
460- . get ( pos + offset)
461- && let ty:: Param ( _) = arg. kind ( )
462448 {
463- let place = & self . move_data . move_paths [ mpi] . place ;
464- let ty = place. ty ( self . body , self . infcx . tcx ) . ty ;
465- if let ty:: Ref ( _, _, hir:: Mutability :: Mut ) = ty. kind ( ) {
449+ // The move occurred as one of the arguments to a function call. Is that
450+ // argument generic? `def_id` can't be a closure here, so using `fn_sig` is fine
451+ let arg_param = if self . infcx . tcx . def_kind ( def_id) . is_fn_like ( )
452+ && let Some ( arg_ty) = self
453+ . infcx
454+ . tcx
455+ . fn_sig ( def_id)
456+ . instantiate_identity ( )
457+ . skip_binder ( )
458+ . inputs ( )
459+ . get ( pos + offset)
460+ && let ty:: Param ( arg_param) = arg_ty. kind ( )
461+ {
462+ Some ( arg_param)
463+ } else {
464+ None
465+ } ;
466+
467+ // If the moved value is a mut reference, it is used in a
468+ // generic function and it's type is a generic param, it can be
469+ // reborrowed to avoid moving.
470+ // for example:
471+ // struct Y(u32);
472+ // x's type is '& mut Y' and it is used in `fn generic<T>(x: T) {}`.
473+ if let ty:: Ref ( _, _, hir:: Mutability :: Mut ) = ty. kind ( )
474+ && arg_param. is_some ( )
475+ {
466476 * has_suggest_reborrow = true ;
467477 self . suggest_reborrow ( err, expr. span , moved_place) ;
468478 return ;
469479 }
470- }
471480
472- let mut can_suggest_clone = true ;
473- if let Some ( def_id) = def_id
474- && let Some ( local_def_id) = def_id. as_local ( )
475- && let node = self . infcx . tcx . hir_node_by_def_id ( local_def_id)
476- && let Some ( fn_sig) = node. fn_sig ( )
477- && let Some ( ident) = node. ident ( )
478- && let Some ( pos) = args. iter ( ) . position ( |arg| arg. hir_id == expr. hir_id )
479- && let Some ( arg) = fn_sig. decl . inputs . get ( pos + offset)
480- {
481481 let mut is_mut = false ;
482- if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = arg. kind
483- && let Res :: Def ( DefKind :: TyParam , param_def_id) = path. res
482+ if let Some ( param) = arg_param
484483 && self
485484 . infcx
486485 . tcx
@@ -497,10 +496,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
497496 self . infcx . tcx . get_diagnostic_item ( sym:: BorrowMut ) ,
498497 ]
499498 . contains ( & Some ( predicate. def_id ( ) ) )
500- && let ty:: Param ( param) = predicate. self_ty ( ) . kind ( )
501- && let generics = self . infcx . tcx . generics_of ( def_id)
502- && let param = generics. type_param ( * param, self . infcx . tcx )
503- && param. def_id == param_def_id
499+ && * predicate. self_ty ( ) . kind ( ) == ty:: Param ( * param)
504500 {
505501 if [
506502 self . infcx . tcx . get_diagnostic_item ( sym:: AsMut ) ,
@@ -522,10 +518,17 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
522518 expr. span . shrink_to_lo ( ) ,
523519 "borrow the value to avoid moving it" ,
524520 format ! ( "&{}" , if is_mut { "mut " } else { "" } ) ,
525- Applicability :: MachineApplicable ,
521+ Applicability :: MaybeIncorrect ,
526522 ) ;
527523 can_suggest_clone = is_mut;
528- } else {
524+ } else if let Some ( local_def_id) = def_id. as_local ( )
525+ && let node = self . infcx . tcx . hir_node_by_def_id ( local_def_id)
526+ && let Some ( fn_decl) = node. fn_decl ( )
527+ && let Some ( ident) = node. ident ( )
528+ && let Some ( arg) = fn_decl. inputs . get ( pos + offset)
529+ {
530+ // If we can't suggest borrowing in the call, but the function definition
531+ // is local, instead offer changing the function to borrow that argument.
529532 let mut span: MultiSpan = arg. span . into ( ) ;
530533 span. push_span_label (
531534 arg. span ,
@@ -546,8 +549,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
546549 ) ;
547550 }
548551 }
549- let place = & self . move_data . move_paths [ mpi] . place ;
550- let ty = place. ty ( self . body , self . infcx . tcx ) . ty ;
551552 if let hir:: Node :: Expr ( parent_expr) = parent
552553 && let hir:: ExprKind :: Call ( call_expr, _) = parent_expr. kind
553554 && let hir:: ExprKind :: Path ( hir:: QPath :: LangItem ( LangItem :: IntoIterIntoIter , _) ) =
0 commit comments