@@ -610,6 +610,12 @@ enum LocalMutationIsAllowed {
610
610
No
611
611
}
612
612
613
+ struct AccessErrorsReported {
614
+ mutability_error : bool ,
615
+ #[ allow( dead_code) ]
616
+ conflict_error : bool
617
+ }
618
+
613
619
#[ derive( Copy , Clone ) ]
614
620
enum InitializationRequiringAction {
615
621
Update ,
@@ -652,7 +658,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
652
658
kind : ( ShallowOrDeep , ReadOrWrite ) ,
653
659
is_local_mutation_allowed : LocalMutationIsAllowed ,
654
660
flow_state : & Flows < ' cx , ' gcx , ' tcx > ,
655
- ) {
661
+ ) -> AccessErrorsReported {
656
662
let ( sd, rw) = kind;
657
663
658
664
let storage_dead_or_drop_local = match ( place_span. 0 , rw) {
@@ -663,14 +669,38 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
663
669
// Check if error has already been reported to stop duplicate reporting.
664
670
if let Some ( local) = storage_dead_or_drop_local {
665
671
if self . storage_dead_or_drop_error_reported . contains ( & local) {
666
- return ;
672
+ return AccessErrorsReported {
673
+ mutability_error : false ,
674
+ conflict_error : true
675
+ } ;
667
676
}
668
677
}
669
678
670
- // Check permissions
671
- let mut error_reported =
679
+ let mutability_error =
672
680
self . check_access_permissions ( place_span, rw, is_local_mutation_allowed) ;
681
+ let conflict_error =
682
+ self . check_access_for_conflict ( context, place_span, sd, rw, flow_state) ;
673
683
684
+ // A conflict with a storagedead/drop is a "borrow does not live long enough"
685
+ // error. Avoid reporting such an error multiple times for the same local.
686
+ if conflict_error {
687
+ if let Some ( local) = storage_dead_or_drop_local {
688
+ self . storage_dead_or_drop_error_reported . insert ( local) ;
689
+ }
690
+ }
691
+
692
+ AccessErrorsReported { mutability_error, conflict_error }
693
+ }
694
+
695
+ fn check_access_for_conflict (
696
+ & mut self ,
697
+ context : Context ,
698
+ place_span : ( & Place < ' tcx > , Span ) ,
699
+ sd : ShallowOrDeep ,
700
+ rw : ReadOrWrite ,
701
+ flow_state : & Flows < ' cx , ' gcx , ' tcx > ,
702
+ ) -> bool {
703
+ let mut error_reported = false ;
674
704
self . each_borrow_involving_path (
675
705
context,
676
706
( sd, place_span. 0 ) ,
@@ -742,11 +772,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
742
772
} ,
743
773
) ;
744
774
745
- if error_reported {
746
- if let Some ( local) = storage_dead_or_drop_local {
747
- self . storage_dead_or_drop_error_reported . insert ( local) ;
748
- }
749
- }
775
+ error_reported
750
776
}
751
777
752
778
fn mutate_place (
@@ -772,16 +798,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
772
798
}
773
799
}
774
800
775
- self . access_place (
801
+ let errors_reported = self . access_place (
776
802
context,
777
803
place_span,
778
804
( kind, Write ( WriteKind :: Mutate ) ) ,
779
805
LocalMutationIsAllowed :: Yes ,
780
806
flow_state,
781
807
) ;
782
808
783
- // check for reassignments to immutable local variables
784
- self . check_if_reassignment_to_immutable_state ( context, place_span, flow_state) ;
809
+ if !errors_reported. mutability_error {
810
+ // check for reassignments to immutable local variables
811
+ self . check_if_reassignment_to_immutable_state ( context, place_span, flow_state) ;
812
+ }
785
813
}
786
814
787
815
fn consume_rvalue (
@@ -988,10 +1016,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
988
1016
return ;
989
1017
}
990
1018
991
- if let Err ( _) = self . is_mutable ( place, LocalMutationIsAllowed :: Yes ) {
992
- return ;
993
- }
994
-
995
1019
match self . move_path_closest_to ( place) {
996
1020
Ok ( mpi) => for ii in & move_data. init_path_map [ mpi] {
997
1021
if flow_state. ever_inits . contains ( ii) {
0 commit comments