@@ -440,47 +440,46 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
440
440
} else {
441
441
( None , & [ ] [ ..] , 0 )
442
442
} ;
443
+ let ty = place. ty ( self . body , self . infcx . tcx ) . ty ;
443
444
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 ;
450
446
if let Some ( def_id) = def_id
451
- && self . infcx . tcx . def_kind ( def_id) . is_fn_like ( )
452
447
&& 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 ( )
462
448
{
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
+ {
466
476
* has_suggest_reborrow = true ;
467
477
self . suggest_reborrow ( err, expr. span , moved_place) ;
468
478
return ;
469
479
}
470
- }
471
480
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
- {
481
481
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
484
483
&& self
485
484
. infcx
486
485
. tcx
@@ -497,10 +496,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
497
496
self . infcx . tcx . get_diagnostic_item ( sym:: BorrowMut ) ,
498
497
]
499
498
. 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)
504
500
{
505
501
if [
506
502
self . infcx . tcx . get_diagnostic_item ( sym:: AsMut ) ,
@@ -522,10 +518,17 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
522
518
expr. span . shrink_to_lo ( ) ,
523
519
"borrow the value to avoid moving it" ,
524
520
format ! ( "&{}" , if is_mut { "mut " } else { "" } ) ,
525
- Applicability :: MachineApplicable ,
521
+ Applicability :: MaybeIncorrect ,
526
522
) ;
527
523
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.
529
532
let mut span: MultiSpan = arg. span . into ( ) ;
530
533
span. push_span_label (
531
534
arg. span ,
@@ -546,8 +549,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
546
549
) ;
547
550
}
548
551
}
549
- let place = & self . move_data . move_paths [ mpi] . place ;
550
- let ty = place. ty ( self . body , self . infcx . tcx ) . ty ;
551
552
if let hir:: Node :: Expr ( parent_expr) = parent
552
553
&& let hir:: ExprKind :: Call ( call_expr, _) = parent_expr. kind
553
554
&& let hir:: ExprKind :: Path ( hir:: QPath :: LangItem ( LangItem :: IntoIterIntoIter , _) ) =
0 commit comments