@@ -9,6 +9,7 @@ use rustc_middle::bug;
9
9
use rustc_middle:: mir:: * ;
10
10
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
11
11
use rustc_mir_dataflow:: move_paths:: { LookupResult , MovePathIndex } ;
12
+ use rustc_span:: def_id:: DefId ;
12
13
use rustc_span:: { BytePos , DUMMY_SP , ExpnKind , MacroKind , Span } ;
13
14
use rustc_trait_selection:: error_reporting:: traits:: FindExprBySpan ;
14
15
use rustc_trait_selection:: infer:: InferCtxtExt ;
@@ -507,38 +508,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
507
508
) ;
508
509
509
510
let closure_span = tcx. def_span ( def_id) ;
510
- let mut clause_span = DUMMY_SP ;
511
- let typck_result = self . infcx . tcx . typeck ( self . mir_def_id ( ) ) ;
512
- if let Some ( closure_def_id) = def_id. as_local ( )
513
- && let hir:: Node :: Expr ( expr) = tcx. hir_node_by_def_id ( closure_def_id)
514
- && let hir:: Node :: Expr ( parent) = tcx. parent_hir_node ( expr. hir_id )
515
- && let hir:: ExprKind :: Call ( callee, _) = parent. kind
516
- && let Some ( ty) = typck_result. node_type_opt ( callee. hir_id )
517
- && let ty:: FnDef ( fn_def_id, args) = ty. kind ( )
518
- && let predicates = tcx. predicates_of ( fn_def_id) . instantiate ( tcx, args)
519
- && let Some ( ( _, span) ) =
520
- predicates. predicates . iter ( ) . zip ( predicates. spans . iter ( ) ) . find (
521
- |( pred, _) | match pred. as_trait_clause ( ) {
522
- Some ( clause)
523
- if let ty:: Closure ( clause_closure_def_id, _) =
524
- clause. self_ty ( ) . skip_binder ( ) . kind ( )
525
- && clause_closure_def_id == def_id
526
- && ( tcx. lang_items ( ) . fn_mut_trait ( )
527
- == Some ( clause. def_id ( ) )
528
- || tcx. lang_items ( ) . fn_trait ( )
529
- == Some ( clause. def_id ( ) ) ) =>
530
- {
531
- // Found `<TyOfCapturingClosure as FnMut>`
532
- true
533
- }
534
- _ => false ,
535
- } ,
536
- )
537
- {
538
- // We point at the `Fn()` or `FnMut()` bound that coerced the closure, which
539
- // could be changed to `FnOnce()` to avoid the move error.
540
- clause_span = * span;
541
- }
542
511
543
512
self . cannot_move_out_of ( span, & place_description)
544
513
. with_span_label ( upvar_span, "captured outer variable" )
@@ -547,7 +516,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
547
516
format ! ( "captured by this `{closure_kind}` closure" ) ,
548
517
)
549
518
. with_span_help (
550
- clause_span ,
519
+ self . get_closure_bound_clause_span ( * def_id ) ,
551
520
"`Fn` and `FnMut` closures require captured values to be able to be \
552
521
consumed multiple times, but an `FnOnce` consume them only once",
553
522
)
@@ -599,6 +568,45 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
599
568
err
600
569
}
601
570
571
+ fn get_closure_bound_clause_span ( & self , def_id : DefId ) -> Span {
572
+ let tcx = self . infcx . tcx ;
573
+ let typeck_result = tcx. typeck ( self . mir_def_id ( ) ) ;
574
+ let Some ( closure_def_id) = def_id. as_local ( ) else { return DUMMY_SP } ;
575
+ let hir:: Node :: Expr ( expr) = tcx. hir_node_by_def_id ( closure_def_id) else { return DUMMY_SP } ;
576
+ let hir:: Node :: Expr ( parent) = tcx. parent_hir_node ( expr. hir_id ) else { return DUMMY_SP } ;
577
+ let predicates = match parent. kind {
578
+ hir:: ExprKind :: Call ( callee, _) => {
579
+ let Some ( ty) = typeck_result. node_type_opt ( callee. hir_id ) else { return DUMMY_SP } ;
580
+ let ty:: FnDef ( fn_def_id, args) = ty. kind ( ) else { return DUMMY_SP } ;
581
+ tcx. predicates_of ( fn_def_id) . instantiate ( tcx, args)
582
+ }
583
+ hir:: ExprKind :: MethodCall ( ..) => {
584
+ let Some ( ( _, method) ) = typeck_result. type_dependent_def ( parent. hir_id ) else {
585
+ return DUMMY_SP ;
586
+ } ;
587
+ let args = typeck_result. node_args ( parent. hir_id ) ;
588
+ tcx. predicates_of ( method) . instantiate ( tcx, args)
589
+ }
590
+ _ => return DUMMY_SP ,
591
+ } ;
592
+ for ( pred, span) in predicates. predicates . iter ( ) . zip ( predicates. spans . iter ( ) ) {
593
+ tracing:: info!( ?pred) ;
594
+ tracing:: info!( ?span) ;
595
+ if let Some ( clause) = pred. as_trait_clause ( )
596
+ && let ty:: Closure ( clause_closure_def_id, _) = clause. self_ty ( ) . skip_binder ( ) . kind ( )
597
+ && * clause_closure_def_id == def_id
598
+ && ( tcx. lang_items ( ) . fn_mut_trait ( ) == Some ( clause. def_id ( ) )
599
+ || tcx. lang_items ( ) . fn_trait ( ) == Some ( clause. def_id ( ) ) )
600
+ {
601
+ // Found `<TyOfCapturingClosure as FnMut>`
602
+ // We point at the `Fn()` or `FnMut()` bound that coerced the closure, which
603
+ // could be changed to `FnOnce()` to avoid the move error.
604
+ return * span;
605
+ }
606
+ }
607
+ DUMMY_SP
608
+ }
609
+
602
610
fn add_move_hints ( & self , error : GroupedMoveError < ' tcx > , err : & mut Diag < ' _ > , span : Span ) {
603
611
match error {
604
612
GroupedMoveError :: MovesFromPlace { mut binds_to, move_from, .. } => {
0 commit comments