@@ -798,12 +798,6 @@ enum LocalMutationIsAllowed {
798
798
No ,
799
799
}
800
800
801
- struct AccessErrorsReported {
802
- mutability_error : bool ,
803
- #[ allow( dead_code) ]
804
- conflict_error : bool ,
805
- }
806
-
807
801
#[ derive( Copy , Clone ) ]
808
802
enum InitializationRequiringAction {
809
803
Update ,
@@ -1072,7 +1066,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1072
1066
kind : ( ShallowOrDeep , ReadOrWrite ) ,
1073
1067
is_local_mutation_allowed : LocalMutationIsAllowed ,
1074
1068
flow_state : & Flows < ' cx , ' gcx , ' tcx > ,
1075
- ) -> AccessErrorsReported {
1069
+ ) {
1076
1070
let ( sd, rw) = kind;
1077
1071
1078
1072
if let Activation ( _, borrow_index) = rw {
@@ -1082,10 +1076,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1082
1076
place: {:?} borrow_index: {:?}",
1083
1077
place_span. 0 , borrow_index
1084
1078
) ;
1085
- return AccessErrorsReported {
1086
- mutability_error : false ,
1087
- conflict_error : true ,
1088
- } ;
1079
+ return ;
1089
1080
}
1090
1081
}
1091
1082
@@ -1097,10 +1088,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1097
1088
"access_place: suppressing error place_span=`{:?}` kind=`{:?}`" ,
1098
1089
place_span, kind
1099
1090
) ;
1100
- return AccessErrorsReported {
1101
- mutability_error : false ,
1102
- conflict_error : true ,
1103
- } ;
1091
+ return ;
1104
1092
}
1105
1093
1106
1094
let mutability_error =
@@ -1122,11 +1110,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1122
1110
self . access_place_error_reported
1123
1111
. insert ( ( place_span. 0 . clone ( ) , place_span. 1 ) ) ;
1124
1112
}
1125
-
1126
- AccessErrorsReported {
1127
- mutability_error,
1128
- conflict_error,
1129
- }
1130
1113
}
1131
1114
1132
1115
fn check_access_for_conflict (
@@ -1275,23 +1258,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1275
1258
}
1276
1259
}
1277
1260
1278
- let errors_reported = self . access_place (
1261
+ // Special case: you can assign a immutable local variable
1262
+ // (e.g., `x = ...`) so long as it has never been initialized
1263
+ // before (at this point in the flow).
1264
+ if let & Place :: Local ( local) = place_span. 0 {
1265
+ if let Mutability :: Not = self . mir . local_decls [ local] . mutability {
1266
+ // check for reassignments to immutable local variables
1267
+ self . check_if_reassignment_to_immutable_state (
1268
+ context,
1269
+ local,
1270
+ place_span,
1271
+ flow_state,
1272
+ ) ;
1273
+ return ;
1274
+ }
1275
+ }
1276
+
1277
+ // Otherwise, use the normal access permission rules.
1278
+ self . access_place (
1279
1279
context,
1280
1280
place_span,
1281
1281
( kind, Write ( WriteKind :: Mutate ) ) ,
1282
- // We want immutable upvars to cause an "assignment to immutable var"
1283
- // error, not an "reassignment of immutable var" error, because the
1284
- // latter can't find a good previous assignment span.
1285
- //
1286
- // There's probably a better way to do this.
1287
- LocalMutationIsAllowed :: ExceptUpvars ,
1282
+ LocalMutationIsAllowed :: No ,
1288
1283
flow_state,
1289
1284
) ;
1290
-
1291
- if !errors_reported. mutability_error {
1292
- // check for reassignments to immutable local variables
1293
- self . check_if_reassignment_to_immutable_state ( context, place_span, flow_state) ;
1294
- }
1295
1285
}
1296
1286
1297
1287
fn consume_rvalue (
@@ -1590,27 +1580,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1590
1580
fn check_if_reassignment_to_immutable_state (
1591
1581
& mut self ,
1592
1582
context : Context ,
1593
- ( place, span) : ( & Place < ' tcx > , Span ) ,
1583
+ local : Local ,
1584
+ place_span : ( & Place < ' tcx > , Span ) ,
1594
1585
flow_state : & Flows < ' cx , ' gcx , ' tcx > ,
1595
1586
) {
1596
- debug ! ( "check_if_reassignment_to_immutable_state({:?})" , place) ;
1597
- // determine if this path has a non-mut owner (and thus needs checking).
1598
- let err_place = match self . is_mutable ( place, LocalMutationIsAllowed :: No ) {
1599
- Ok ( ..) => return ,
1600
- Err ( place) => place,
1601
- } ;
1602
- debug ! (
1603
- "check_if_reassignment_to_immutable_state({:?}) - is an imm local" ,
1604
- place
1605
- ) ;
1606
-
1607
- for i in flow_state. ever_inits . iter_incoming ( ) {
1608
- let init = self . move_data . inits [ i] ;
1609
- let init_place = & self . move_data . move_paths [ init. path ] . place ;
1610
- if places_conflict:: places_conflict ( self . tcx , self . mir , & init_place, place, Deep ) {
1611
- self . report_illegal_reassignment ( context, ( place, span) , init. span , err_place) ;
1612
- break ;
1613
- }
1587
+ debug ! ( "check_if_reassignment_to_immutable_state({:?})" , local) ;
1588
+
1589
+ // Check if any of the initializiations of `local` have happened yet:
1590
+ let mpi = self . move_data . rev_lookup . find_local ( local) ;
1591
+ let init_indices = & self . move_data . init_path_map [ mpi] ;
1592
+ let first_init_index = init_indices. iter ( ) . find ( |ii| flow_state. ever_inits . contains ( ii) ) ;
1593
+ if let Some ( & init_index) = first_init_index {
1594
+ // And, if so, report an error.
1595
+ let init = & self . move_data . inits [ init_index] ;
1596
+ self . report_illegal_reassignment ( context, place_span, init. span , place_span. 0 ) ;
1614
1597
}
1615
1598
}
1616
1599
0 commit comments