@@ -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
@@ -483,7 +474,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
483
474
self . cannot_move_out_of_interior_noncopy ( span, ty, None )
484
475
}
485
476
ty:: Closure ( def_id, closure_args)
486
- if def_id. as_local ( ) == Some ( self . mir_def_id ( ) ) && upvar_field. is_some ( ) =>
477
+ if def_id. as_local ( ) == Some ( self . mir_def_id ( ) )
478
+ && let Some ( upvar_field) = upvar_field =>
487
479
{
488
480
let closure_kind_ty = closure_args. as_closure ( ) . kind_ty ( ) ;
489
481
let closure_kind = match closure_kind_ty. to_opt_closure_kind ( ) {
@@ -496,7 +488,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
496
488
let capture_description =
497
489
format ! ( "captured variable in an `{closure_kind}` closure" ) ;
498
490
499
- let upvar = & self . upvars [ upvar_field. unwrap ( ) . index ( ) ] ;
491
+ let upvar = & self . upvars [ upvar_field. index ( ) ] ;
500
492
let upvar_hir_id = upvar. get_root_variable ( ) ;
501
493
let upvar_name = upvar. to_string ( tcx) ;
502
494
let upvar_span = tcx. hir_span ( upvar_hir_id) ;
@@ -606,7 +598,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
606
598
}
607
599
// No binding. Nothing to suggest.
608
600
GroupedMoveError :: OtherIllegalMove { ref original_path, use_spans, .. } => {
609
- let use_span = use_spans. var_or_use ( ) ;
601
+ let mut use_span = use_spans. var_or_use ( ) ;
610
602
let place_ty = original_path. ty ( self . body , self . infcx . tcx ) . ty ;
611
603
let place_desc = match self . describe_place ( original_path. as_ref ( ) ) {
612
604
Some ( desc) => format ! ( "`{desc}`" ) ,
@@ -623,19 +615,59 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
623
615
) ;
624
616
}
625
617
618
+ if let Some ( upvar_field) = self
619
+ . prefixes ( original_path. as_ref ( ) , PrefixSet :: All )
620
+ . find_map ( |p| self . is_upvar_field_projection ( p) )
621
+ {
622
+ // Look for the introduction of the original binding being moved.
623
+ let upvar = & self . upvars [ upvar_field. index ( ) ] ;
624
+ let upvar_hir_id = upvar. get_root_variable ( ) ;
625
+ use_span = match self . infcx . tcx . parent_hir_node ( upvar_hir_id) {
626
+ hir:: Node :: Param ( param) => {
627
+ // Instead of pointing at the path where we access the value within a
628
+ // closure, we point at the type of the outer `fn` argument.
629
+ param. ty_span
630
+ }
631
+ hir:: Node :: LetStmt ( stmt) => match ( stmt. ty , stmt. init ) {
632
+ // We point at the type of the outer let-binding.
633
+ ( Some ( ty) , _) => ty. span ,
634
+ // We point at the initializer of the outer let-binding, but only if it
635
+ // isn't something that spans multiple lines, like a closure, as the
636
+ // ASCII art gets messy.
637
+ ( None , Some ( init) )
638
+ if !self . infcx . tcx . sess . source_map ( ) . is_multiline ( init. span ) =>
639
+ {
640
+ init. span
641
+ }
642
+ _ => use_span,
643
+ } ,
644
+ _ => use_span,
645
+ } ;
646
+ }
647
+
626
648
err. subdiagnostic ( crate :: session_diagnostics:: TypeNoCopy :: Label {
627
649
is_partial_move : false ,
628
650
ty : place_ty,
629
651
place : & place_desc,
630
652
span : use_span,
631
653
} ) ;
632
654
655
+ let mut pointed_at_span = false ;
633
656
use_spans. args_subdiag ( err, |args_span| {
657
+ if args_span == span || args_span == use_span {
658
+ pointed_at_span = true ;
659
+ }
634
660
crate :: session_diagnostics:: CaptureArgLabel :: MoveOutPlace {
635
- place : place_desc,
661
+ place : place_desc. clone ( ) ,
636
662
args_span,
637
663
}
638
664
} ) ;
665
+ if !pointed_at_span && use_span != span {
666
+ err. subdiagnostic ( crate :: session_diagnostics:: CaptureArgLabel :: MoveOutPlace {
667
+ place : place_desc,
668
+ args_span : span,
669
+ } ) ;
670
+ }
639
671
640
672
self . add_note_for_packed_struct_derive ( err, original_path. local ) ;
641
673
}
0 commit comments