@@ -1207,7 +1207,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12071207 & mut self ,
12081208 span : Span ,
12091209 scrutinee_span : Span ,
1210- start_block : BasicBlock ,
1210+ mut start_block : BasicBlock ,
12111211 otherwise_block : BasicBlock ,
12121212 candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
12131213 fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
@@ -1219,14 +1219,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12191219 debug ! ( "match_candidates: {:?} candidates fully matched" , fully_matched) ;
12201220 let ( matched_candidates, unmatched_candidates) = candidates. split_at_mut ( fully_matched) ;
12211221
1222- let block = self . select_matched_candidates ( matched_candidates, start_block, fake_borrows) ;
1222+ for candidate in matched_candidates. iter_mut ( ) {
1223+ start_block = self . select_matched_candidate ( candidate, start_block, fake_borrows) ;
1224+ }
12231225
12241226 // If there are no candidates that still need testing, we're
12251227 // done. Since all matches are exhaustive, execution should
12261228 // never reach this point.
12271229 if unmatched_candidates. is_empty ( ) {
12281230 let source_info = self . source_info ( span) ;
1229- self . cfg . goto ( block , source_info, otherwise_block) ;
1231+ self . cfg . goto ( start_block , source_info, otherwise_block) ;
12301232 return ;
12311233 }
12321234
@@ -1235,7 +1237,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12351237 span,
12361238 scrutinee_span,
12371239 unmatched_candidates,
1238- block ,
1240+ start_block ,
12391241 otherwise_block,
12401242 fake_borrows,
12411243 ) ;
@@ -1260,67 +1262,64 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12601262 /// * the [otherwise block] of the third pattern to a block with an
12611263 /// [`Unreachable` terminator](TerminatorKind::Unreachable).
12621264 ///
1263- /// In addition, we add fake edges from the otherwise blocks to the
1265+ /// In addition, we later add fake edges from the otherwise blocks to the
12641266 /// pre-binding block of the next candidate in the original set of
12651267 /// candidates.
12661268 ///
12671269 /// [pre-binding block]: Candidate::pre_binding_block
12681270 /// [otherwise block]: Candidate::otherwise_block
1269- fn select_matched_candidates (
1271+ fn select_matched_candidate (
12701272 & mut self ,
1271- matched_candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1273+ candidate : & mut Candidate < ' _ , ' tcx > ,
12721274 start_block : BasicBlock ,
12731275 fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
12741276 ) -> BasicBlock {
1275- let mut next_prebinding = start_block;
1276- for candidate in matched_candidates. iter_mut ( ) {
1277- assert ! ( candidate. otherwise_block. is_none( ) ) ;
1278- assert ! ( candidate. pre_binding_block. is_none( ) ) ;
1279- debug_assert ! (
1280- candidate. subcandidates. is_empty( ) ,
1281- "subcandidates should be empty in select_matched_candidates" ,
1282- ) ;
1277+ assert ! ( candidate. otherwise_block. is_none( ) ) ;
1278+ assert ! ( candidate. pre_binding_block. is_none( ) ) ;
1279+ debug_assert ! (
1280+ candidate. subcandidates. is_empty( ) ,
1281+ "subcandidates should be empty in select_matched_candidates" ,
1282+ ) ;
12831283
1284- if let Some ( fake_borrows) = fake_borrows {
1285- // Insert a borrows of prefixes of places that are bound and are
1286- // behind a dereference projection.
1287- //
1288- // These borrows are taken to avoid situations like the following:
1289- //
1290- // match x[10] {
1291- // _ if { x = &[0]; false } => (),
1292- // y => (), // Out of bounds array access!
1293- // }
1294- //
1295- // match *x {
1296- // // y is bound by reference in the guard and then by copy in the
1297- // // arm, so y is 2 in the arm!
1298- // y if { y == 1 && (x = &2) == () } => y,
1299- // _ => 3,
1300- // }
1301- for Binding { source, .. } in & candidate. bindings {
1302- if let Some ( i) =
1303- source. projection . iter ( ) . rposition ( |elem| elem == ProjectionElem :: Deref )
1304- {
1305- let proj_base = & source. projection [ ..i] ;
1306-
1307- fake_borrows. insert ( Place {
1308- local : source. local ,
1309- projection : self . tcx . mk_place_elems ( proj_base) ,
1310- } ) ;
1311- }
1284+ if let Some ( fake_borrows) = fake_borrows {
1285+ // Insert a borrows of prefixes of places that are bound and are
1286+ // behind a dereference projection.
1287+ //
1288+ // These borrows are taken to avoid situations like the following:
1289+ //
1290+ // match x[10] {
1291+ // _ if { x = &[0]; false } => (),
1292+ // y => (), // Out of bounds array access!
1293+ // }
1294+ //
1295+ // match *x {
1296+ // // y is bound by reference in the guard and then by copy in the
1297+ // // arm, so y is 2 in the arm!
1298+ // y if { y == 1 && (x = &2) == () } => y,
1299+ // _ => 3,
1300+ // }
1301+ for Binding { source, .. } in & candidate. bindings {
1302+ if let Some ( i) =
1303+ source. projection . iter ( ) . rposition ( |elem| elem == ProjectionElem :: Deref )
1304+ {
1305+ let proj_base = & source. projection [ ..i] ;
1306+
1307+ fake_borrows. insert ( Place {
1308+ local : source. local ,
1309+ projection : self . tcx . mk_place_elems ( proj_base) ,
1310+ } ) ;
13121311 }
13131312 }
1313+ }
13141314
1315- candidate. pre_binding_block = Some ( next_prebinding) ;
1316- next_prebinding = self . cfg . start_new_block ( ) ;
1317- if candidate. has_guard {
1318- // Create the otherwise block for this candidate, which is the
1319- // pre-binding block for the next candidate.
1320- candidate. otherwise_block = Some ( next_prebinding) ;
1321- }
1315+ candidate. pre_binding_block = Some ( start_block) ;
1316+ let otherwise_block = self . cfg . start_new_block ( ) ;
1317+ if candidate. has_guard {
1318+ // Create the otherwise block for this candidate, which is the
1319+ // pre-binding block for the next candidate.
1320+ candidate. otherwise_block = Some ( otherwise_block) ;
13221321 }
1323- next_prebinding
1322+ otherwise_block
13241323 }
13251324
13261325 /// Tests a candidate where there are only or-patterns left to test, or
0 commit comments