@@ -115,10 +115,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
115115 fn append_to_grouped_errors (
116116 & self ,
117117 grouped_errors : & mut Vec < GroupedMoveError < ' tcx > > ,
118- error : MoveError < ' tcx > ,
118+ MoveError { place : original_path , location , kind } : MoveError < ' tcx > ,
119119 ) {
120- let MoveError { place : original_path, location, kind } = error;
121-
122120 // Note: that the only time we assign a place isn't a temporary
123121 // to a user variable is when initializing it.
124122 // If that ever stops being the case, then the ever initialized
@@ -251,54 +249,47 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
251249 }
252250
253251 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,
276281 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) )
280289 }
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- )
299290 } ;
300291
301- self . add_move_hints ( error, & mut err, err_span ) ;
292+ self . add_move_hints ( error, & mut err, span ) ;
302293 self . buffer_error ( err) ;
303294 }
304295
@@ -483,7 +474,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
483474 self . cannot_move_out_of_interior_noncopy ( span, ty, None )
484475 }
485476 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 =>
487479 {
488480 let closure_kind_ty = closure_args. as_closure ( ) . kind_ty ( ) ;
489481 let closure_kind = match closure_kind_ty. to_opt_closure_kind ( ) {
@@ -496,7 +488,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
496488 let capture_description =
497489 format ! ( "captured variable in an `{closure_kind}` closure" ) ;
498490
499- let upvar = & self . upvars [ upvar_field. unwrap ( ) . index ( ) ] ;
491+ let upvar = & self . upvars [ upvar_field. index ( ) ] ;
500492 let upvar_hir_id = upvar. get_root_variable ( ) ;
501493 let upvar_name = upvar. to_string ( tcx) ;
502494 let upvar_span = tcx. hir_span ( upvar_hir_id) ;
@@ -606,7 +598,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
606598 }
607599 // No binding. Nothing to suggest.
608600 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 ( ) ;
610602 let place_ty = original_path. ty ( self . body , self . infcx . tcx ) . ty ;
611603 let place_desc = match self . describe_place ( original_path. as_ref ( ) ) {
612604 Some ( desc) => format ! ( "`{desc}`" ) ,
@@ -623,19 +615,59 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
623615 ) ;
624616 }
625617
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+
626648 err. subdiagnostic ( crate :: session_diagnostics:: TypeNoCopy :: Label {
627649 is_partial_move : false ,
628650 ty : place_ty,
629651 place : & place_desc,
630652 span : use_span,
631653 } ) ;
632654
655+ let mut pointed_at_span = false ;
633656 use_spans. args_subdiag ( err, |args_span| {
657+ if args_span == span || args_span == use_span {
658+ pointed_at_span = true ;
659+ }
634660 crate :: session_diagnostics:: CaptureArgLabel :: MoveOutPlace {
635- place : place_desc,
661+ place : place_desc. clone ( ) ,
636662 args_span,
637663 }
638664 } ) ;
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+ }
639671
640672 self . add_note_for_packed_struct_derive ( err, original_path. local ) ;
641673 }
0 commit comments