@@ -115,10 +115,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
115
115
fn append_to_grouped_errors (
116
116
& self ,
117
117
grouped_errors : & mut Vec < GroupedMoveError < ' tcx > > ,
118
- error : MoveError < ' tcx > ,
118
+ MoveError { place : original_path , ___location , kind } : MoveError < ' tcx > ,
119
119
) {
120
- let MoveError { place : original_path, ___location, kind } = error;
121
-
122
120
// Note: that the only time we assign a place isn't a temporary
123
121
// to a user variable is when initializing it.
124
122
// If that ever stops being the case, then the ever initialized
@@ -251,54 +249,47 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
251
249
}
252
250
253
251
fn report ( & mut self , error : GroupedMoveError < ' tcx > ) {
254
- let ( mut err, err_span) = {
255
- let ( span, use_spans, original_path, kind) = match error {
256
- GroupedMoveError :: MovesFromPlace { span, original_path, ref kind, .. }
257
- | GroupedMoveError :: MovesFromValue { span, original_path, ref kind, .. } => {
258
- ( span, None , original_path, kind)
259
- }
260
- GroupedMoveError :: OtherIllegalMove { use_spans, original_path, ref kind } => {
261
- ( use_spans. args_or_use ( ) , Some ( use_spans) , original_path, kind)
262
- }
263
- } ;
264
- debug ! (
265
- "report: original_path={:?} span={:?}, kind={:?} \
266
- original_path.is_upvar_field_projection={:?}",
267
- original_path,
268
- span,
269
- kind,
270
- self . is_upvar_field_projection( original_path. as_ref( ) )
271
- ) ;
272
- if self . has_ambiguous_copy ( original_path. ty ( self . body , self . infcx . tcx ) . ty ) {
273
- // If the type may implement Copy, skip the error.
274
- // It's an error with the Copy implementation (e.g. duplicate Copy) rather than borrow check
275
- self . dcx ( ) . span_delayed_bug (
252
+ let ( span, use_spans, original_path, kind) = match error {
253
+ GroupedMoveError :: MovesFromPlace { span, original_path, ref kind, .. }
254
+ | GroupedMoveError :: MovesFromValue { span, original_path, ref kind, .. } => {
255
+ ( span, None , original_path, kind)
256
+ }
257
+ GroupedMoveError :: OtherIllegalMove { use_spans, original_path, ref kind } => {
258
+ ( use_spans. args_or_use ( ) , Some ( use_spans) , original_path, kind)
259
+ }
260
+ } ;
261
+ debug ! (
262
+ "report: original_path={:?} span={:?}, kind={:?} \
263
+ original_path.is_upvar_field_projection={:?}",
264
+ original_path,
265
+ span,
266
+ kind,
267
+ self . is_upvar_field_projection( original_path. as_ref( ) )
268
+ ) ;
269
+ if self . has_ambiguous_copy ( original_path. ty ( self . body , self . infcx . tcx ) . ty ) {
270
+ // If the type may implement Copy, skip the error.
271
+ // It's an error with the Copy implementation (e.g. duplicate Copy) rather than borrow check
272
+ self . dcx ( )
273
+ . span_delayed_bug ( span, "Type may implement copy, but there is no other error." ) ;
274
+ return ;
275
+ }
276
+ let mut err = match kind {
277
+ & IllegalMoveOriginKind :: BorrowedContent { target_place } => self
278
+ . report_cannot_move_from_borrowed_content (
279
+ original_path,
280
+ target_place,
276
281
span,
277
- "Type may implement copy, but there is no other error." ,
278
- ) ;
279
- return ;
282
+ use_spans,
283
+ ) ,
284
+ & IllegalMoveOriginKind :: InteriorOfTypeWithDestructor { container_ty : ty } => {
285
+ self . cannot_move_out_of_interior_of_drop ( span, ty)
286
+ }
287
+ & IllegalMoveOriginKind :: InteriorOfSliceOrArray { ty, is_index } => {
288
+ self . cannot_move_out_of_interior_noncopy ( span, ty, Some ( is_index) )
280
289
}
281
- (
282
- match kind {
283
- & IllegalMoveOriginKind :: BorrowedContent { target_place } => self
284
- . report_cannot_move_from_borrowed_content (
285
- original_path,
286
- target_place,
287
- span,
288
- use_spans,
289
- ) ,
290
- & IllegalMoveOriginKind :: InteriorOfTypeWithDestructor { container_ty : ty } => {
291
- self . cannot_move_out_of_interior_of_drop ( span, ty)
292
- }
293
- & IllegalMoveOriginKind :: InteriorOfSliceOrArray { ty, is_index } => {
294
- self . cannot_move_out_of_interior_noncopy ( span, ty, Some ( is_index) )
295
- }
296
- } ,
297
- span,
298
- )
299
290
} ;
300
291
301
- self . add_move_hints ( error, & mut err, err_span ) ;
292
+ self . add_move_hints ( error, & mut err, span ) ;
302
293
self . buffer_error ( err) ;
303
294
}
304
295
@@ -482,7 +473,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
482
473
self . cannot_move_out_of_interior_noncopy ( span, ty, None )
483
474
}
484
475
ty:: Closure ( def_id, closure_args)
485
- if def_id. as_local ( ) == Some ( self . mir_def_id ( ) ) && upvar_field. is_some ( ) =>
476
+ if def_id. as_local ( ) == Some ( self . mir_def_id ( ) )
477
+ && let Some ( upvar_field) = upvar_field =>
486
478
{
487
479
let closure_kind_ty = closure_args. as_closure ( ) . kind_ty ( ) ;
488
480
let closure_kind = match closure_kind_ty. to_opt_closure_kind ( ) {
@@ -495,7 +487,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
495
487
let capture_description =
496
488
format ! ( "captured variable in an `{closure_kind}` closure" ) ;
497
489
498
- let upvar = & self . upvars [ upvar_field. unwrap ( ) . index ( ) ] ;
490
+ let upvar = & self . upvars [ upvar_field. index ( ) ] ;
499
491
let upvar_hir_id = upvar. get_root_variable ( ) ;
500
492
let upvar_name = upvar. to_string ( tcx) ;
501
493
let upvar_span = tcx. hir_span ( upvar_hir_id) ;
@@ -604,8 +596,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
604
596
self . add_move_error_details ( err, & binds_to) ;
605
597
}
606
598
// No binding. Nothing to suggest.
607
- GroupedMoveError :: OtherIllegalMove { ref original_path, use_spans, .. } => {
608
- let use_span = use_spans. var_or_use ( ) ;
599
+ GroupedMoveError :: OtherIllegalMove {
600
+ ref original_path, use_spans, ref kind, ..
601
+ } => {
602
+ let mut use_span = use_spans. var_or_use ( ) ;
609
603
let place_ty = original_path. ty ( self . body , self . infcx . tcx ) . ty ;
610
604
let place_desc = match self . describe_place ( original_path. as_ref ( ) ) {
611
605
Some ( desc) => format ! ( "`{desc}`" ) ,
@@ -622,6 +616,39 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
622
616
) ;
623
617
}
624
618
619
+ if let IllegalMoveOriginKind :: BorrowedContent { target_place } = & kind
620
+ && let ty = target_place. ty ( self . body , self . infcx . tcx ) . ty
621
+ && let ty:: Closure ( def_id, _) = ty. kind ( )
622
+ && def_id. as_local ( ) == Some ( self . mir_def_id ( ) )
623
+ && let Some ( upvar_field) = self
624
+ . prefixes ( original_path. as_ref ( ) , PrefixSet :: All )
625
+ . find_map ( |p| self . is_upvar_field_projection ( p) )
626
+ && let upvar = & self . upvars [ upvar_field. index ( ) ]
627
+ && let upvar_hir_id = upvar. get_root_variable ( )
628
+ && let hir:: Node :: Param ( param) = self . infcx . tcx . parent_hir_node ( upvar_hir_id)
629
+ {
630
+ // Instead of pointing at the path where we access the value within a closure,
631
+ // we point at the type on the parameter from the definition of the outer
632
+ // function:
633
+ //
634
+ // error[E0507]: cannot move out of `foo`, a captured
635
+ // variable in an `Fn` closure
636
+ // --> file.rs:14:25
637
+ // |
638
+ // 13 | fn do_stuff(foo: Option<Foo>) {
639
+ // | --- ----------- move occurs because `foo` has type
640
+ // | | `Option<Foo>`, which does not implement
641
+ // | | the `Copy` trait
642
+ // | captured outer variable
643
+ // 14 | require_fn_trait(|| async {
644
+ // | -- ^^^^^ `foo` is moved here
645
+ // | |
646
+ // | captured by this `Fn` closure
647
+ // 15 | if foo.map_or(false, |f| f.foo()) {
648
+ // | --- variable moved due to use in coroutine
649
+ use_span = param. ty_span ;
650
+ }
651
+
625
652
err. subdiagnostic ( crate :: session_diagnostics:: TypeNoCopy :: Label {
626
653
is_partial_move : false ,
627
654
ty : place_ty,
0 commit comments