@@ -993,6 +993,10 @@ struct Candidate<'pat, 'tcx> {
993
993
/// If the candidate matches, bindings and ascriptions must be established.
994
994
extra_data : PatternExtraData < ' tcx > ,
995
995
996
+ /// If we filled `self.subcandidate`, we store here the span of the or-pattern they came from.
997
+ // Invariant: it is `None` iff `subcandidates.is_empty()`.
998
+ or_span : Option < Span > ,
999
+
996
1000
/// The block before the `bindings` have been established.
997
1001
pre_binding_block : Option < BasicBlock > ,
998
1002
/// The pre-binding block of the next candidate.
@@ -1015,6 +1019,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
1015
1019
extra_data : flat_pat. extra_data ,
1016
1020
has_guard,
1017
1021
subcandidates : Vec :: new ( ) ,
1022
+ or_span : None ,
1018
1023
otherwise_block : None ,
1019
1024
pre_binding_block : None ,
1020
1025
next_candidate_pre_binding_block : None ,
@@ -1248,7 +1253,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1248
1253
//
1249
1254
// only generates a single switch.
1250
1255
candidate. subcandidates = self . create_or_subcandidates ( pats, candidate. has_guard ) ;
1251
- candidate. match_pairs . pop ( ) ;
1256
+ let first_match_pair = candidate. match_pairs . pop ( ) . unwrap ( ) ;
1257
+ candidate. or_span = Some ( first_match_pair. pattern . span ) ;
1252
1258
split_or_candidate = true ;
1253
1259
}
1254
1260
}
@@ -1502,16 +1508,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1502
1508
& mut or_candidate_refs,
1503
1509
) ;
1504
1510
candidate. subcandidates = or_candidates;
1505
- self . merge_trivial_subcandidates ( candidate, self . source_info ( or_span) ) ;
1511
+ candidate. or_span = Some ( or_span) ;
1512
+ self . merge_trivial_subcandidates ( candidate) ;
1506
1513
}
1507
1514
1508
1515
/// Try to merge all of the subcandidates of the given candidate into one.
1509
1516
/// This avoids exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`.
1510
- fn merge_trivial_subcandidates (
1511
- & mut self ,
1512
- candidate : & mut Candidate < ' _ , ' tcx > ,
1513
- source_info : SourceInfo ,
1514
- ) {
1517
+ fn merge_trivial_subcandidates ( & mut self , candidate : & mut Candidate < ' _ , ' tcx > ) {
1515
1518
if candidate. subcandidates . is_empty ( ) || candidate. has_guard {
1516
1519
// FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
1517
1520
return ;
@@ -1521,7 +1524,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1521
1524
1522
1525
// Not `Iterator::all` because we don't want to short-circuit.
1523
1526
for subcandidate in & mut candidate. subcandidates {
1524
- self . merge_trivial_subcandidates ( subcandidate, source_info ) ;
1527
+ self . merge_trivial_subcandidates ( subcandidate) ;
1525
1528
1526
1529
// FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
1527
1530
can_merge &=
@@ -1530,10 +1533,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1530
1533
1531
1534
if can_merge {
1532
1535
let any_matches = self . cfg . start_new_block ( ) ;
1536
+ let source_info = self . source_info ( candidate. or_span . unwrap ( ) ) ;
1533
1537
for subcandidate in mem:: take ( & mut candidate. subcandidates ) {
1534
1538
let or_block = subcandidate. pre_binding_block . unwrap ( ) ;
1535
1539
self . cfg . goto ( or_block, source_info, any_matches) ;
1536
1540
}
1541
+ candidate. or_span = None ;
1537
1542
candidate. pre_binding_block = Some ( any_matches) ;
1538
1543
}
1539
1544
}
0 commit comments