@@ -9,6 +9,7 @@ use rustc_middle::bug;
99use rustc_middle:: mir:: * ;
1010use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
1111use rustc_mir_dataflow:: move_paths:: { LookupResult , MovePathIndex } ;
12+ use rustc_span:: def_id:: DefId ;
1213use rustc_span:: { BytePos , DUMMY_SP , ExpnKind , MacroKind , Span } ;
1314use rustc_trait_selection:: error_reporting:: traits:: FindExprBySpan ;
1415use rustc_trait_selection:: infer:: InferCtxtExt ;
@@ -507,38 +508,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
507508 ) ;
508509
509510 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- }
542511
543512 self . cannot_move_out_of ( span, & place_description)
544513 . with_span_label ( upvar_span, "captured outer variable" )
@@ -547,7 +516,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
547516 format ! ( "captured by this `{closure_kind}` closure" ) ,
548517 )
549518 . with_span_help (
550- clause_span ,
519+ self . get_closure_bound_clause_span ( * def_id ) ,
551520 "`Fn` and `FnMut` closures require captured values to be able to be \
552521 consumed multiple times, but an `FnOnce` consume them only once",
553522 )
@@ -599,6 +568,45 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
599568 err
600569 }
601570
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+
602610 fn add_move_hints ( & self , error : GroupedMoveError < ' tcx > , err : & mut Diag < ' _ > , span : Span ) {
603611 match error {
604612 GroupedMoveError :: MovesFromPlace { mut binds_to, move_from, .. } => {
0 commit comments