@@ -798,12 +798,6 @@ enum LocalMutationIsAllowed {
798798 No ,
799799}
800800
801- struct AccessErrorsReported {
802- mutability_error : bool ,
803- #[ allow( dead_code) ]
804- conflict_error : bool ,
805- }
806-
807801#[ derive( Copy , Clone ) ]
808802enum InitializationRequiringAction {
809803 Update ,
@@ -1072,7 +1066,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
10721066 kind : ( ShallowOrDeep , ReadOrWrite ) ,
10731067 is_local_mutation_allowed : LocalMutationIsAllowed ,
10741068 flow_state : & Flows < ' cx , ' gcx , ' tcx > ,
1075- ) -> AccessErrorsReported {
1069+ ) {
10761070 let ( sd, rw) = kind;
10771071
10781072 if let Activation ( _, borrow_index) = rw {
@@ -1082,10 +1076,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
10821076 place: {:?} borrow_index: {:?}",
10831077 place_span. 0 , borrow_index
10841078 ) ;
1085- return AccessErrorsReported {
1086- mutability_error : false ,
1087- conflict_error : true ,
1088- } ;
1079+ return ;
10891080 }
10901081 }
10911082
@@ -1097,10 +1088,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
10971088 "access_place: suppressing error place_span=`{:?}` kind=`{:?}`" ,
10981089 place_span, kind
10991090 ) ;
1100- return AccessErrorsReported {
1101- mutability_error : false ,
1102- conflict_error : true ,
1103- } ;
1091+ return ;
11041092 }
11051093
11061094 let mutability_error =
@@ -1122,11 +1110,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
11221110 self . access_place_error_reported
11231111 . insert ( ( place_span. 0 . clone ( ) , place_span. 1 ) ) ;
11241112 }
1125-
1126- AccessErrorsReported {
1127- mutability_error,
1128- conflict_error,
1129- }
11301113 }
11311114
11321115 fn check_access_for_conflict (
@@ -1275,23 +1258,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
12751258 }
12761259 }
12771260
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 (
12791279 context,
12801280 place_span,
12811281 ( 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 ,
12881283 flow_state,
12891284 ) ;
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- }
12951285 }
12961286
12971287 fn consume_rvalue (
@@ -1590,27 +1580,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
15901580 fn check_if_reassignment_to_immutable_state (
15911581 & mut self ,
15921582 context : Context ,
1593- ( place, span) : ( & Place < ' tcx > , Span ) ,
1583+ local : Local ,
1584+ place_span : ( & Place < ' tcx > , Span ) ,
15941585 flow_state : & Flows < ' cx , ' gcx , ' tcx > ,
15951586 ) {
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 ) ;
16141597 }
16151598 }
16161599
0 commit comments