@@ -340,7 +340,7 @@ fn do_mir_borrowck<'tcx>(
340
340
next_region_name : RefCell :: new ( 1 ) ,
341
341
polonius_output : None ,
342
342
errors,
343
- to_skip : Default :: default ( ) ,
343
+ replaces : Default :: default ( ) ,
344
344
} ;
345
345
promoted_mbcx. report_move_errors ( move_errors) ;
346
346
errors = promoted_mbcx. errors ;
@@ -372,7 +372,7 @@ fn do_mir_borrowck<'tcx>(
372
372
next_region_name : RefCell :: new ( 1 ) ,
373
373
polonius_output,
374
374
errors,
375
- to_skip : Default :: default ( ) ,
375
+ replaces : Default :: default ( ) ,
376
376
} ;
377
377
378
378
// Compute and report region errors, if any.
@@ -556,7 +556,9 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
556
556
557
557
errors : error:: BorrowckErrors < ' tcx > ,
558
558
559
- to_skip : FxHashSet < Location > ,
559
+ /// Record the places were a replace happens so that we can use the
560
+ /// correct access depth in the assignment for better diagnostic
561
+ replaces : FxHashSet < Location > ,
560
562
}
561
563
562
564
// Check that:
@@ -581,9 +583,10 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
581
583
match & stmt. kind {
582
584
StatementKind :: Assign ( box ( lhs, rhs) ) => {
583
585
self . consume_rvalue ( location, ( rhs, span) , flow_state) ;
584
- if !self . to_skip . contains ( & location) {
585
- self . mutate_place ( location, ( * lhs, span) , Shallow ( None ) , flow_state) ;
586
- }
586
+ // In case of a replace the drop access check is skipped for better diagnostic but we need
587
+ // to use a stricter access depth here
588
+ let access_depth = if self . replaces . contains ( & location) { AccessDepth :: Drop } else { Shallow ( None ) } ;
589
+ self . mutate_place ( location, ( * lhs, span) , access_depth, flow_state) ;
587
590
}
588
591
StatementKind :: FakeRead ( box ( _, place) ) => {
589
592
// Read for match doesn't access any memory and is used to
@@ -656,36 +659,28 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
656
659
loc, term, place, span
657
660
) ;
658
661
659
- let next_statement = if * is_replace {
660
- self . body ( )
661
- . basic_blocks
662
- . get ( * target)
663
- . expect ( "MIR should be complete at this point" )
664
- . statements
665
- . first ( )
666
- } else {
667
- None
668
- } ;
669
-
670
- match next_statement {
671
- Some ( Statement { kind : StatementKind :: Assign ( _) , source_info : _ } ) => {
672
- // this is a drop from a replace operation, for better diagnostic report
673
- // here possible conflicts and mute the assign statement errors
674
- self . to_skip . insert ( Location { block : * target, statement_index : 0 } ) ;
675
- self . to_skip
676
- . insert ( Location { block : unwind. unwrap ( ) , statement_index : 0 } ) ;
677
- self . mutate_place ( loc, ( * place, span) , AccessDepth :: Deep , flow_state) ;
678
- }
679
- _ => {
680
- self . access_place (
681
- loc,
682
- ( * place, span) ,
683
- ( AccessDepth :: Drop , Write ( WriteKind :: StorageDeadOrDrop ) ) ,
684
- LocalMutationIsAllowed :: Yes ,
685
- flow_state,
686
- ) ;
662
+ // In case of a replace, it's more user friendly to report a problem with the explicit
663
+ // assignment than the implicit drop.
664
+ // Simply skip this access and rely on the assignment to report any error.
665
+ if * is_replace {
666
+ // An assignment `x = ...` is usually a shallow access, but in the case of a replace
667
+ // the drop could access internal references depending on the drop implementation.
668
+ // Since we're skipping the drop access, we need to mark the access depth
669
+ // of the assignment as AccessDepth::Drop.
670
+ self . replaces . insert ( Location { block : * target, statement_index : 0 } ) ;
671
+ if let Some ( unwind) = unwind {
672
+ self . replaces . insert ( Location { block : * unwind, statement_index : 0 } ) ;
687
673
}
674
+ return ;
688
675
}
676
+
677
+ self . access_place (
678
+ loc,
679
+ ( * place, span) ,
680
+ ( AccessDepth :: Drop , Write ( WriteKind :: StorageDeadOrDrop ) ) ,
681
+ LocalMutationIsAllowed :: Yes ,
682
+ flow_state,
683
+ )
689
684
}
690
685
TerminatorKind :: Call {
691
686
func,
0 commit comments