@@ -1012,6 +1012,10 @@ struct Candidate<'pat, 'tcx> {
1012
1012
/// If the candidate matches, bindings and ascriptions must be established.
1013
1013
extra_data : PatternExtraData < ' tcx > ,
1014
1014
1015
+ /// If we filled `self.subcandidate`, we store here the span of the or-pattern they came from.
1016
+ // Invariant: it is `None` iff `subcandidates.is_empty()`.
1017
+ or_span : Option < Span > ,
1018
+
1015
1019
/// The block before the `bindings` have been established.
1016
1020
pre_binding_block : Option < BasicBlock > ,
1017
1021
/// The pre-binding block of the next candidate.
@@ -1034,6 +1038,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
1034
1038
extra_data : flat_pat. extra_data ,
1035
1039
has_guard,
1036
1040
subcandidates : Vec :: new ( ) ,
1041
+ or_span : None ,
1037
1042
otherwise_block : None ,
1038
1043
pre_binding_block : None ,
1039
1044
next_candidate_pre_binding_block : None ,
@@ -1290,7 +1295,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1290
1295
//
1291
1296
// only generates a single switch.
1292
1297
candidate. subcandidates = self . create_or_subcandidates ( pats, candidate. has_guard ) ;
1293
- candidate. match_pairs . pop ( ) ;
1298
+ let first_match_pair = candidate. match_pairs . pop ( ) . unwrap ( ) ;
1299
+ candidate. or_span = Some ( first_match_pair. pattern . span ) ;
1294
1300
split_or_candidate = true ;
1295
1301
}
1296
1302
}
@@ -1544,16 +1550,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1544
1550
& mut or_candidate_refs,
1545
1551
) ;
1546
1552
candidate. subcandidates = or_candidates;
1547
- self . merge_trivial_subcandidates ( candidate, self . source_info ( or_span) ) ;
1553
+ candidate. or_span = Some ( or_span) ;
1554
+ self . merge_trivial_subcandidates ( candidate) ;
1548
1555
}
1549
1556
1550
1557
/// Try to merge all of the subcandidates of the given candidate into one.
1551
1558
/// This avoids exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`.
1552
- fn merge_trivial_subcandidates (
1553
- & mut self ,
1554
- candidate : & mut Candidate < ' _ , ' tcx > ,
1555
- source_info : SourceInfo ,
1556
- ) {
1559
+ fn merge_trivial_subcandidates ( & mut self , candidate : & mut Candidate < ' _ , ' tcx > ) {
1557
1560
if candidate. subcandidates . is_empty ( ) || candidate. has_guard {
1558
1561
// FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
1559
1562
return ;
@@ -1563,7 +1566,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1563
1566
1564
1567
// Not `Iterator::all` because we don't want to short-circuit.
1565
1568
for subcandidate in & mut candidate. subcandidates {
1566
- self . merge_trivial_subcandidates ( subcandidate, source_info ) ;
1569
+ self . merge_trivial_subcandidates ( subcandidate) ;
1567
1570
1568
1571
// FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
1569
1572
can_merge &=
@@ -1572,10 +1575,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1572
1575
1573
1576
if can_merge {
1574
1577
let any_matches = self . cfg . start_new_block ( ) ;
1578
+ let source_info = self . source_info ( candidate. or_span . unwrap ( ) ) ;
1575
1579
for subcandidate in mem:: take ( & mut candidate. subcandidates ) {
1576
1580
let or_block = subcandidate. pre_binding_block . unwrap ( ) ;
1577
1581
self . cfg . goto ( or_block, source_info, any_matches) ;
1578
1582
}
1583
+ candidate. or_span = None ;
1579
1584
candidate. pre_binding_block = Some ( any_matches) ;
1580
1585
}
1581
1586
}
0 commit comments