@@ -1744,8 +1744,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1744
1744
/// Try to merge all of the subcandidates of the given candidate into one. This avoids
1745
1745
/// exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`. The candidate should have been
1746
1746
/// expanded with `create_or_subcandidates`.
1747
+ ///
1748
+ /// Note that this takes place _after_ the subcandidates have participated
1749
+ /// in match tree lowering.
1747
1750
fn merge_trivial_subcandidates ( & mut self , candidate : & mut Candidate < ' _ , ' tcx > ) {
1748
- if candidate. subcandidates . is_empty ( ) || candidate. has_guard {
1751
+ assert ! ( !candidate. subcandidates. is_empty( ) ) ;
1752
+ if candidate. has_guard {
1749
1753
// FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
1750
1754
return ;
1751
1755
}
@@ -1759,20 +1763,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1759
1763
}
1760
1764
1761
1765
let mut last_otherwise = None ;
1762
- let any_matches = self . cfg . start_new_block ( ) ;
1766
+ let shared_pre_binding_block = self . cfg . start_new_block ( ) ;
1767
+ // This candidate is about to become a leaf, so unset `or_span`.
1763
1768
let or_span = candidate. or_span . take ( ) . unwrap ( ) ;
1764
1769
let source_info = self . source_info ( or_span) ;
1765
1770
1766
1771
if candidate. false_edge_start_block . is_none ( ) {
1767
1772
candidate. false_edge_start_block = candidate. subcandidates [ 0 ] . false_edge_start_block ;
1768
1773
}
1769
1774
1775
+ // Remove the (known-trivial) subcandidates from the candidate tree,
1776
+ // so that they aren't visible after match tree lowering, and wire them
1777
+ // all to join up at a single shared pre-binding block.
1778
+ // (Note that the subcandidates have already had their part of the match
1779
+ // tree lowered by this point, which is why we can add a goto to them.)
1770
1780
for subcandidate in mem:: take ( & mut candidate. subcandidates ) {
1771
- let or_block = subcandidate. pre_binding_block . unwrap ( ) ;
1772
- self . cfg . goto ( or_block , source_info, any_matches ) ;
1781
+ let subcandidate_block = subcandidate. pre_binding_block . unwrap ( ) ;
1782
+ self . cfg . goto ( subcandidate_block , source_info, shared_pre_binding_block ) ;
1773
1783
last_otherwise = subcandidate. otherwise_block ;
1774
1784
}
1775
- candidate. pre_binding_block = Some ( any_matches ) ;
1785
+ candidate. pre_binding_block = Some ( shared_pre_binding_block ) ;
1776
1786
assert ! ( last_otherwise. is_some( ) ) ;
1777
1787
candidate. otherwise_block = last_otherwise;
1778
1788
}
0 commit comments