@@ -315,20 +315,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
315315 // The set of places that we are creating fake borrows of. If there are
316316 // no match guards then we don't need any fake borrows, so don't track
317317 // them.
318- let mut fake_borrows = match_has_guard. then ( FxIndexSet :: default) ;
318+ let fake_borrows = match_has_guard
319+ . then ( || util:: FakeBorrowCollector :: collect_fake_borrows ( self , candidates) ) ;
319320
320321 let otherwise_block = self . cfg . start_new_block ( ) ;
321322
322323 // This will generate code to test scrutinee_place and
323324 // branch to the appropriate arm block
324- self . match_candidates (
325- match_start_span,
326- scrutinee_span,
327- block,
328- otherwise_block,
329- candidates,
330- & mut fake_borrows,
331- ) ;
325+ self . match_candidates ( match_start_span, scrutinee_span, block, otherwise_block, candidates) ;
332326
333327 // See the doc comment on `match_candidates` for why we may have an
334328 // otherwise block. Match checking will ensure this is actually
@@ -938,6 +932,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
938932 }
939933}
940934
935+ /// A pattern in a form suitable for generating code.
936+ #[ derive( Debug , Clone ) ]
937+ struct FlatPat < ' pat , ' tcx > {
938+ /// [`Span`] of the original pattern.
939+ span : Span ,
940+
941+ /// To match the pattern, all of these must be satisfied...
942+ // Invariant: all the `MatchPair`s are recursively simplified.
943+ // Invariant: or-patterns must be sorted to the end.
944+ match_pairs : Vec < MatchPair < ' pat , ' tcx > > ,
945+
946+ /// ...these bindings established...
947+ bindings : Vec < Binding < ' tcx > > ,
948+
949+ /// ...and these types asserted.
950+ ascriptions : Vec < Ascription < ' tcx > > ,
951+ }
952+
953+ impl < ' tcx , ' pat > FlatPat < ' pat , ' tcx > {
954+ fn new (
955+ place : PlaceBuilder < ' tcx > ,
956+ pattern : & ' pat Pat < ' tcx > ,
957+ cx : & mut Builder < ' _ , ' tcx > ,
958+ ) -> Self {
959+ let mut match_pairs = vec ! [ MatchPair :: new( place, pattern, cx) ] ;
960+ let mut bindings = Vec :: new ( ) ;
961+ let mut ascriptions = Vec :: new ( ) ;
962+
963+ cx. simplify_match_pairs ( & mut match_pairs, & mut bindings, & mut ascriptions) ;
964+
965+ FlatPat { span : pattern. span , match_pairs, bindings, ascriptions }
966+ }
967+ }
968+
941969#[ derive( Debug ) ]
942970struct Candidate < ' pat , ' tcx > {
943971 /// [`Span`] of the original pattern that gave rise to this candidate.
@@ -952,11 +980,11 @@ struct Candidate<'pat, 'tcx> {
952980 match_pairs : Vec < MatchPair < ' pat , ' tcx > > ,
953981
954982 /// ...these bindings established...
955- // Invariant: not mutated outside `Candidate::new()` .
983+ // Invariant: not mutated after candidate creation .
956984 bindings : Vec < Binding < ' tcx > > ,
957985
958986 /// ...and these types asserted...
959- // Invariant: not mutated outside `Candidate::new()` .
987+ // Invariant: not mutated after candidate creation .
960988 ascriptions : Vec < Ascription < ' tcx > > ,
961989
962990 /// ...and if this is non-empty, one of these subcandidates also has to match...
@@ -978,25 +1006,21 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
9781006 has_guard : bool ,
9791007 cx : & mut Builder < ' _ , ' tcx > ,
9801008 ) -> Self {
981- let mut candidate = Candidate {
982- span : pattern. span ,
1009+ Self :: from_flat_pat ( FlatPat :: new ( place, pattern, cx) , has_guard)
1010+ }
1011+
1012+ fn from_flat_pat ( flat_pat : FlatPat < ' pat , ' tcx > , has_guard : bool ) -> Self {
1013+ Candidate {
1014+ span : flat_pat. span ,
1015+ match_pairs : flat_pat. match_pairs ,
1016+ bindings : flat_pat. bindings ,
1017+ ascriptions : flat_pat. ascriptions ,
9831018 has_guard,
984- match_pairs : vec ! [ MatchPair :: new( place, pattern, cx) ] ,
985- bindings : Vec :: new ( ) ,
986- ascriptions : Vec :: new ( ) ,
9871019 subcandidates : Vec :: new ( ) ,
9881020 otherwise_block : None ,
9891021 pre_binding_block : None ,
9901022 next_candidate_pre_binding_block : None ,
991- } ;
992-
993- cx. simplify_match_pairs (
994- & mut candidate. match_pairs ,
995- & mut candidate. bindings ,
996- & mut candidate. ascriptions ,
997- ) ;
998-
999- candidate
1023+ }
10001024 }
10011025
10021026 /// Visit the leaf candidates (those with no subcandidates) contained in
@@ -1059,7 +1083,7 @@ enum TestCase<'pat, 'tcx> {
10591083 Constant { value : mir:: Const < ' tcx > } ,
10601084 Range ( & ' pat PatRange < ' tcx > ) ,
10611085 Slice { len : usize , variable_length : bool } ,
1062- Or ,
1086+ Or { pats : Box < [ FlatPat < ' pat , ' tcx > ] > } ,
10631087}
10641088
10651089#[ derive( Debug , Clone ) ]
@@ -1205,19 +1229,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12051229 ///
12061230 /// Note how we test `x` twice. This is the tradeoff of backtracking automata: we prefer smaller
12071231 /// code size at the expense of non-optimal code paths.
1208- #[ instrument( skip( self , fake_borrows ) , level = "debug" ) ]
1232+ #[ instrument( skip( self ) , level = "debug" ) ]
12091233 fn match_candidates < ' pat > (
12101234 & mut self ,
12111235 span : Span ,
12121236 scrutinee_span : Span ,
12131237 start_block : BasicBlock ,
12141238 otherwise_block : BasicBlock ,
12151239 candidates : & mut [ & mut Candidate < ' pat , ' tcx > ] ,
1216- fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
12171240 ) {
12181241 let mut split_or_candidate = false ;
12191242 for candidate in & mut * candidates {
1220- if let [ MatchPair { pattern : Pat { kind : PatKind :: Or { pats } , .. } , place , .. } ] =
1243+ if let [ MatchPair { test_case : TestCase :: Or { pats, .. } , .. } ] =
12211244 & * candidate. match_pairs
12221245 {
12231246 // Split a candidate in which the only match-pair is an or-pattern into multiple
@@ -1229,8 +1252,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12291252 // }
12301253 //
12311254 // only generates a single switch.
1232- candidate. subcandidates =
1233- self . create_or_subcandidates ( place, pats, candidate. has_guard ) ;
1255+ candidate. subcandidates = self . create_or_subcandidates ( pats, candidate. has_guard ) ;
12341256 candidate. match_pairs . pop ( ) ;
12351257 split_or_candidate = true ;
12361258 }
@@ -1251,7 +1273,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12511273 start_block,
12521274 otherwise_block,
12531275 & mut * new_candidates,
1254- fake_borrows,
12551276 ) ;
12561277 } else {
12571278 self . match_simplified_candidates (
@@ -1260,7 +1281,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12601281 start_block,
12611282 otherwise_block,
12621283 candidates,
1263- fake_borrows,
12641284 ) ;
12651285 }
12661286 } ) ;
@@ -1273,7 +1293,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12731293 mut start_block : BasicBlock ,
12741294 otherwise_block : BasicBlock ,
12751295 candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1276- fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
12771296 ) {
12781297 match candidates {
12791298 [ ] => {
@@ -1285,14 +1304,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12851304 [ first, remaining @ ..] if first. match_pairs . is_empty ( ) => {
12861305 // The first candidate has satisfied all its match pairs; we link it up and continue
12871306 // with the remaining candidates.
1288- start_block = self . select_matched_candidate ( first, start_block, fake_borrows ) ;
1307+ start_block = self . select_matched_candidate ( first, start_block) ;
12891308 self . match_simplified_candidates (
12901309 span,
12911310 scrutinee_span,
12921311 start_block,
12931312 otherwise_block,
12941313 remaining,
1295- fake_borrows,
12961314 )
12971315 }
12981316 candidates => {
@@ -1303,7 +1321,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13031321 candidates,
13041322 start_block,
13051323 otherwise_block,
1306- fake_borrows,
13071324 ) ;
13081325 }
13091326 }
@@ -1338,43 +1355,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13381355 & mut self ,
13391356 candidate : & mut Candidate < ' _ , ' tcx > ,
13401357 start_block : BasicBlock ,
1341- fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
13421358 ) -> BasicBlock {
13431359 assert ! ( candidate. otherwise_block. is_none( ) ) ;
13441360 assert ! ( candidate. pre_binding_block. is_none( ) ) ;
13451361 assert ! ( candidate. subcandidates. is_empty( ) ) ;
13461362
1347- if let Some ( fake_borrows) = fake_borrows {
1348- // Insert a borrows of prefixes of places that are bound and are
1349- // behind a dereference projection.
1350- //
1351- // These borrows are taken to avoid situations like the following:
1352- //
1353- // match x[10] {
1354- // _ if { x = &[0]; false } => (),
1355- // y => (), // Out of bounds array access!
1356- // }
1357- //
1358- // match *x {
1359- // // y is bound by reference in the guard and then by copy in the
1360- // // arm, so y is 2 in the arm!
1361- // y if { y == 1 && (x = &2) == () } => y,
1362- // _ => 3,
1363- // }
1364- for Binding { source, .. } in & candidate. bindings {
1365- if let Some ( i) =
1366- source. projection . iter ( ) . rposition ( |elem| elem == ProjectionElem :: Deref )
1367- {
1368- let proj_base = & source. projection [ ..i] ;
1369-
1370- fake_borrows. insert ( Place {
1371- local : source. local ,
1372- projection : self . tcx . mk_place_elems ( proj_base) ,
1373- } ) ;
1374- }
1375- }
1376- }
1377-
13781363 candidate. pre_binding_block = Some ( start_block) ;
13791364 let otherwise_block = self . cfg . start_new_block ( ) ;
13801365 if candidate. has_guard {
@@ -1445,38 +1430,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14451430 candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
14461431 start_block : BasicBlock ,
14471432 otherwise_block : BasicBlock ,
1448- fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
14491433 ) {
14501434 let ( first_candidate, remaining_candidates) = candidates. split_first_mut ( ) . unwrap ( ) ;
14511435 assert ! ( first_candidate. subcandidates. is_empty( ) ) ;
1452- if !matches ! ( first_candidate. match_pairs[ 0 ] . pattern. kind, PatKind :: Or { .. } ) {
1453- self . test_candidates (
1454- span,
1455- scrutinee_span,
1456- candidates,
1457- start_block,
1458- otherwise_block,
1459- fake_borrows,
1460- ) ;
1436+ if !matches ! ( first_candidate. match_pairs[ 0 ] . test_case, TestCase :: Or { .. } ) {
1437+ self . test_candidates ( span, scrutinee_span, candidates, start_block, otherwise_block) ;
14611438 return ;
14621439 }
14631440
14641441 let match_pairs = mem:: take ( & mut first_candidate. match_pairs ) ;
14651442 let ( first_match_pair, remaining_match_pairs) = match_pairs. split_first ( ) . unwrap ( ) ;
1466- let PatKind :: Or { ref pats } = & first_match_pair. pattern . kind else { unreachable ! ( ) } ;
1443+ let TestCase :: Or { ref pats } = & first_match_pair. test_case else { unreachable ! ( ) } ;
14671444
14681445 let remainder_start = self . cfg . start_new_block ( ) ;
14691446 let or_span = first_match_pair. pattern . span ;
14701447 // Test the alternatives of this or-pattern.
1471- self . test_or_pattern (
1472- first_candidate,
1473- start_block,
1474- remainder_start,
1475- pats,
1476- or_span,
1477- & first_match_pair. place ,
1478- fake_borrows,
1479- ) ;
1448+ self . test_or_pattern ( first_candidate, start_block, remainder_start, pats, or_span) ;
14801449
14811450 if !remaining_match_pairs. is_empty ( ) {
14821451 // If more match pairs remain, test them after each subcandidate.
@@ -1497,7 +1466,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14971466 & mut [ leaf_candidate] ,
14981467 or_start,
14991468 or_otherwise,
1500- fake_borrows,
15011469 ) ;
15021470 } ) ;
15031471 }
@@ -1509,28 +1477,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15091477 remainder_start,
15101478 otherwise_block,
15111479 remaining_candidates,
1512- fake_borrows,
15131480 ) ;
15141481 }
15151482
15161483 #[ instrument(
1517- skip( self , start_block, otherwise_block, or_span, place , fake_borrows , candidate, pats) ,
1484+ skip( self , start_block, otherwise_block, or_span, candidate, pats) ,
15181485 level = "debug"
15191486 ) ]
15201487 fn test_or_pattern < ' pat > (
15211488 & mut self ,
15221489 candidate : & mut Candidate < ' pat , ' tcx > ,
15231490 start_block : BasicBlock ,
15241491 otherwise_block : BasicBlock ,
1525- pats : & ' pat [ Box < Pat < ' tcx > > ] ,
1492+ pats : & [ FlatPat < ' pat , ' tcx > ] ,
15261493 or_span : Span ,
1527- place : & PlaceBuilder < ' tcx > ,
1528- fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
15291494 ) {
15301495 debug ! ( "candidate={:#?}\n pats={:#?}" , candidate, pats) ;
15311496 let mut or_candidates: Vec < _ > = pats
15321497 . iter ( )
1533- . map ( |pat| Candidate :: new ( place. clone ( ) , pat, candidate. has_guard , self ) )
1498+ . cloned ( )
1499+ . map ( |flat_pat| Candidate :: from_flat_pat ( flat_pat, candidate. has_guard ) )
15341500 . collect ( ) ;
15351501 let mut or_candidate_refs: Vec < _ > = or_candidates. iter_mut ( ) . collect ( ) ;
15361502 self . match_candidates (
@@ -1539,7 +1505,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15391505 start_block,
15401506 otherwise_block,
15411507 & mut or_candidate_refs,
1542- fake_borrows,
15431508 ) ;
15441509 candidate. subcandidates = or_candidates;
15451510 self . merge_trivial_subcandidates ( candidate, self . source_info ( or_span) ) ;
@@ -1599,7 +1564,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15991564 fn pick_test (
16001565 & mut self ,
16011566 candidates : & mut [ & mut Candidate < ' _ , ' tcx > ] ,
1602- fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
16031567 ) -> ( PlaceBuilder < ' tcx > , Test < ' tcx > ) {
16041568 // Extract the match-pair from the highest priority candidate
16051569 let match_pair = & candidates. first ( ) . unwrap ( ) . match_pairs [ 0 ] ;
@@ -1628,13 +1592,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16281592 _ => { }
16291593 }
16301594
1631- // Insert a Shallow borrow of any places that is switched on.
1632- if let Some ( fb) = fake_borrows
1633- && let Some ( resolved_place) = match_place. try_to_place ( self )
1634- {
1635- fb. insert ( resolved_place) ;
1636- }
1637-
16381595 ( match_place, test)
16391596 }
16401597
@@ -1808,10 +1765,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
18081765 candidates : & ' b mut [ & ' c mut Candidate < ' pat , ' tcx > ] ,
18091766 start_block : BasicBlock ,
18101767 otherwise_block : BasicBlock ,
1811- fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
18121768 ) {
18131769 // Extract the match-pair from the highest priority candidate and build a test from it.
1814- let ( match_place, test) = self . pick_test ( candidates, fake_borrows ) ;
1770+ let ( match_place, test) = self . pick_test ( candidates) ;
18151771
18161772 // For each of the N possible test outcomes, build the vector of candidates that applies if
18171773 // the test has that particular outcome.
@@ -1828,7 +1784,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
18281784 remainder_start,
18291785 otherwise_block,
18301786 remaining_candidates,
1831- fake_borrows,
18321787 ) ;
18331788 remainder_start
18341789 } else {
@@ -1850,7 +1805,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
18501805 candidate_start,
18511806 remainder_start,
18521807 & mut * candidates,
1853- fake_borrows,
18541808 ) ;
18551809 candidate_start
18561810 } else {
0 commit comments