@@ -289,42 +289,6 @@ fn opt_eq(tcx: &ty::ctxt, a: &Opt, b: &Opt) -> bool {
289
289
}
290
290
}
291
291
292
- fn opt_overlap ( tcx : & ty:: ctxt , a : & Opt , b : & Opt ) -> bool {
293
- match ( a, b) {
294
- ( & lit( a) , & lit( b) ) => {
295
- let a_expr = lit_to_expr ( tcx, & a) ;
296
- let b_expr = lit_to_expr ( tcx, & b) ;
297
- match const_eval:: compare_lit_exprs ( tcx, a_expr, b_expr) {
298
- Some ( val1) => val1 == 0 ,
299
- None => fail ! ( "opt_overlap: type mismatch" ) ,
300
- }
301
- }
302
-
303
- ( & range( a1, a2) , & range( b1, b2) ) => {
304
- let m1 = const_eval:: compare_lit_exprs ( tcx, a1, b2) ;
305
- let m2 = const_eval:: compare_lit_exprs ( tcx, b1, a2) ;
306
- match ( m1, m2) {
307
- // two ranges [a1, a2] and [b1, b2] overlap iff:
308
- // a1 <= b2 && b1 <= a2
309
- ( Some ( val1) , Some ( val2) ) => ( val1 <= 0 && val2 <= 0 ) ,
310
- _ => fail ! ( "opt_overlap: type mismatch" ) ,
311
- }
312
- }
313
-
314
- ( & range( a1, a2) , & lit( b) ) | ( & lit( b) , & range( a1, a2) ) => {
315
- let b_expr = lit_to_expr ( tcx, & b) ;
316
- let m1 = const_eval:: compare_lit_exprs ( tcx, a1, b_expr) ;
317
- let m2 = const_eval:: compare_lit_exprs ( tcx, a2, b_expr) ;
318
- match ( m1, m2) {
319
- // b is in range [a1, a2] iff a1 <= b and b <= a2
320
- ( Some ( val1) , Some ( val2) ) => ( val1 <= 0 && 0 <= val2) ,
321
- _ => fail ! ( "opt_overlap: type mismatch" ) ,
322
- }
323
- }
324
- _ => fail ! ( "opt_overlap: expect lit or range" )
325
- }
326
- }
327
-
328
292
pub enum opt_result < ' a > {
329
293
single_result( Result < ' a > ) ,
330
294
lower_bound( Result < ' a > ) ,
@@ -562,7 +526,7 @@ fn enter_default<'a, 'b>(
562
526
// Collect all of the matches that can match against anything.
563
527
let matches = enter_match ( bcx, dm, m, col, val, |p| {
564
528
match p. node {
565
- ast:: PatWild | ast:: PatWildMulti | ast :: PatTup ( _ ) => Some ( Vec :: new ( ) ) ,
529
+ ast:: PatWild | ast:: PatWildMulti => Some ( Vec :: new ( ) ) ,
566
530
ast:: PatIdent ( _, _, None ) if pat_is_binding ( dm, p) => Some ( Vec :: new ( ) ) ,
567
531
_ => None
568
532
}
@@ -634,30 +598,16 @@ fn enter_opt<'a, 'b>(
634
598
let tcx = bcx. tcx ( ) ;
635
599
let dummy = @ast:: Pat { id : 0 , node : ast:: PatWild , span : DUMMY_SP } ;
636
600
let mut i = 0 ;
637
- // By the virtue of fact that we are in `trans` already, `enter_opt` is able
638
- // to prune sub-match tree aggressively based on exact equality. But when it
639
- // comes to literal or range, that strategy may lead to wrong result if there
640
- // are guard function or multiple patterns inside tuple; in that case, pruning
641
- // based on the overlap of patterns is required.
642
- //
643
- // Ideally, when constructing the sub-match tree for certain arm, only those
644
- // arms beneath it matter. But that isn't how algorithm works right now and
645
- // all other arms are taken into consideration when computing `guarded` below.
646
- // That is ok since each round of `compile_submatch` guarantees to trim one
647
- // "column" of arm patterns and the algorithm will converge.
648
- let guarded = m. iter ( ) . any ( |x| x. data . arm . guard . is_some ( ) ) ;
649
- let multi_pats = m. len ( ) > 0 && m[ 0 ] . pats . len ( ) > 1 ;
650
601
enter_match ( bcx, & tcx. def_map , m, col, val, |p| {
651
602
let answer = match p. node {
652
603
ast:: PatEnum ( ..) |
653
604
ast:: PatIdent ( _, _, None ) if pat_is_const ( & tcx. def_map , p) => {
654
605
let const_def = tcx. def_map . borrow ( ) . get_copy ( & p. id ) ;
655
606
let const_def_id = ast_util:: def_id_of_def ( const_def) ;
656
- let konst = lit ( ConstLit ( const_def_id) ) ;
657
- match guarded || multi_pats {
658
- false if opt_eq ( tcx, & konst, opt) => Some ( Vec :: new ( ) ) ,
659
- true if opt_overlap ( tcx, & konst, opt) => Some ( Vec :: new ( ) ) ,
660
- _ => None ,
607
+ if opt_eq ( tcx, & lit ( ConstLit ( const_def_id) ) , opt) {
608
+ Some ( Vec :: new ( ) )
609
+ } else {
610
+ None
661
611
}
662
612
}
663
613
ast:: PatEnum ( _, ref subpats) => {
@@ -682,20 +632,12 @@ fn enter_opt<'a, 'b>(
682
632
}
683
633
}
684
634
ast:: PatLit ( l) => {
685
- let lit_expr = lit ( ExprLit ( l) ) ;
686
- match guarded || multi_pats {
687
- false if opt_eq ( tcx, & lit_expr, opt) => Some ( Vec :: new ( ) ) ,
688
- true if opt_overlap ( tcx, & lit_expr, opt) => Some ( Vec :: new ( ) ) ,
689
- _ => None ,
690
- }
635
+ if opt_eq ( tcx, & lit ( ExprLit ( l) ) , opt) { Some ( Vec :: new ( ) ) }
636
+ else { None }
691
637
}
692
638
ast:: PatRange ( l1, l2) => {
693
- let rng = range ( l1, l2) ;
694
- match guarded || multi_pats {
695
- false if opt_eq ( tcx, & rng, opt) => Some ( Vec :: new ( ) ) ,
696
- true if opt_overlap ( tcx, & rng, opt) => Some ( Vec :: new ( ) ) ,
697
- _ => None ,
698
- }
639
+ if opt_eq ( tcx, & range ( l1, l2) , opt) { Some ( Vec :: new ( ) ) }
640
+ else { None }
699
641
}
700
642
ast:: PatStruct ( _, ref field_pats, _) => {
701
643
if opt_eq ( tcx, & variant_opt ( bcx, p. id ) , opt) {
@@ -770,18 +712,7 @@ fn enter_opt<'a, 'b>(
770
712
}
771
713
_ => {
772
714
assert_is_binding_or_wild ( bcx, p) ;
773
- // In most cases, a binding/wildcard match be
774
- // considered to match against any Opt. However, when
775
- // doing vector pattern matching, submatches are
776
- // considered even if the eventual match might be from
777
- // a different submatch. Thus, when a submatch fails
778
- // when doing a vector match, we proceed to the next
779
- // submatch. Thus, including a default match would
780
- // cause the default match to fire spuriously.
781
- match * opt {
782
- vec_len( ..) => None ,
783
- _ => Some ( Vec :: from_elem ( variant_size, dummy) )
784
- }
715
+ Some ( Vec :: from_elem ( variant_size, dummy) )
785
716
}
786
717
} ;
787
718
i += 1 ;
@@ -1421,7 +1352,8 @@ fn compile_guard<'a, 'b>(
1421
1352
data : & ArmData ,
1422
1353
m : & ' a [ Match < ' a , ' b > ] ,
1423
1354
vals : & [ ValueRef ] ,
1424
- chk : & FailureHandler )
1355
+ chk : & FailureHandler ,
1356
+ has_genuine_default : bool )
1425
1357
-> & ' b Block < ' b > {
1426
1358
debug ! ( "compile_guard(bcx={}, guard_expr={}, m={}, vals={})" ,
1427
1359
bcx. to_str( ) ,
@@ -1452,7 +1384,17 @@ fn compile_guard<'a, 'b>(
1452
1384
// Guard does not match: free the values we copied,
1453
1385
// and remove all bindings from the lllocals table
1454
1386
let bcx = drop_bindings ( bcx, data) ;
1455
- compile_submatch ( bcx, m, vals, chk) ;
1387
+ match chk {
1388
+ // If the default arm is the only one left, move on to the next
1389
+ // condition explicitly rather than (possibly) falling back to
1390
+ // the default arm.
1391
+ & JumpToBasicBlock ( _) if m. len ( ) == 1 && has_genuine_default => {
1392
+ Br ( bcx, chk. handle_fail ( ) ) ;
1393
+ }
1394
+ _ => {
1395
+ compile_submatch ( bcx, m, vals, chk, has_genuine_default) ;
1396
+ }
1397
+ } ;
1456
1398
bcx
1457
1399
} ) ;
1458
1400
@@ -1476,7 +1418,8 @@ fn compile_submatch<'a, 'b>(
1476
1418
bcx : & ' b Block < ' b > ,
1477
1419
m : & ' a [ Match < ' a , ' b > ] ,
1478
1420
vals : & [ ValueRef ] ,
1479
- chk : & FailureHandler ) {
1421
+ chk : & FailureHandler ,
1422
+ has_genuine_default : bool ) {
1480
1423
debug ! ( "compile_submatch(bcx={}, m={}, vals={})" ,
1481
1424
bcx. to_str( ) ,
1482
1425
m. repr( bcx. tcx( ) ) ,
@@ -1506,7 +1449,8 @@ fn compile_submatch<'a, 'b>(
1506
1449
m[ 0 ] . data ,
1507
1450
m. slice ( 1 , m. len ( ) ) ,
1508
1451
vals,
1509
- chk) ;
1452
+ chk,
1453
+ has_genuine_default) ;
1510
1454
}
1511
1455
_ => ( )
1512
1456
}
@@ -1524,9 +1468,10 @@ fn compile_submatch<'a, 'b>(
1524
1468
vals,
1525
1469
chk,
1526
1470
col,
1527
- val)
1471
+ val,
1472
+ has_genuine_default)
1528
1473
} else {
1529
- compile_submatch_continue ( bcx, m, vals, chk, col, val)
1474
+ compile_submatch_continue ( bcx, m, vals, chk, col, val, has_genuine_default )
1530
1475
}
1531
1476
}
1532
1477
@@ -1536,7 +1481,8 @@ fn compile_submatch_continue<'a, 'b>(
1536
1481
vals : & [ ValueRef ] ,
1537
1482
chk : & FailureHandler ,
1538
1483
col : uint ,
1539
- val : ValueRef ) {
1484
+ val : ValueRef ,
1485
+ has_genuine_default : bool ) {
1540
1486
let fcx = bcx. fcx ;
1541
1487
let tcx = bcx. tcx ( ) ;
1542
1488
let dm = & tcx. def_map ;
@@ -1570,7 +1516,7 @@ fn compile_submatch_continue<'a, 'b>(
1570
1516
rec_fields. as_slice ( ) ,
1571
1517
val) . as_slice ( ) ,
1572
1518
rec_vals. append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1573
- chk) ;
1519
+ chk, has_genuine_default ) ;
1574
1520
} ) ;
1575
1521
return ;
1576
1522
}
@@ -1595,7 +1541,7 @@ fn compile_submatch_continue<'a, 'b>(
1595
1541
val,
1596
1542
n_tup_elts) . as_slice ( ) ,
1597
1543
tup_vals. append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1598
- chk) ;
1544
+ chk, has_genuine_default ) ;
1599
1545
return ;
1600
1546
}
1601
1547
@@ -1620,7 +1566,7 @@ fn compile_submatch_continue<'a, 'b>(
1620
1566
enter_tuple_struct ( bcx, dm, m, col, val,
1621
1567
struct_element_count) . as_slice ( ) ,
1622
1568
llstructvals. append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1623
- chk) ;
1569
+ chk, has_genuine_default ) ;
1624
1570
return ;
1625
1571
}
1626
1572
@@ -1629,7 +1575,7 @@ fn compile_submatch_continue<'a, 'b>(
1629
1575
compile_submatch ( bcx,
1630
1576
enter_uniq ( bcx, dm, m, col, val) . as_slice ( ) ,
1631
1577
( vec ! ( llbox) ) . append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1632
- chk) ;
1578
+ chk, has_genuine_default ) ;
1633
1579
return ;
1634
1580
}
1635
1581
@@ -1638,7 +1584,7 @@ fn compile_submatch_continue<'a, 'b>(
1638
1584
compile_submatch ( bcx,
1639
1585
enter_region ( bcx, dm, m, col, val) . as_slice ( ) ,
1640
1586
( vec ! ( loaded_val) ) . append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1641
- chk) ;
1587
+ chk, has_genuine_default ) ;
1642
1588
return ;
1643
1589
}
1644
1590
@@ -1695,9 +1641,9 @@ fn compile_submatch_continue<'a, 'b>(
1695
1641
1696
1642
// Compile subtrees for each option
1697
1643
for ( i, opt) in opts. iter ( ) . enumerate ( ) {
1698
- // In some cases in vector pattern matching, we need to override
1699
- // the failure case so that instead of failing, it proceeds to
1700
- // try more matching. branch_chk, then, is the proper failure case
1644
+ // In some cases of range and vector pattern matching, we need to
1645
+ // override the failure case so that instead of failing, it proceeds
1646
+ // to try more matching. branch_chk, then, is the proper failure case
1701
1647
// for the current conditional branch.
1702
1648
let mut branch_chk = None ;
1703
1649
let mut opt_cx = else_cx;
@@ -1747,6 +1693,16 @@ fn compile_submatch_continue<'a, 'b>(
1747
1693
}
1748
1694
} ;
1749
1695
bcx = fcx. new_temp_block ( "compare_next" ) ;
1696
+
1697
+ // If none of the sub-cases match, and the current condition
1698
+ // is guarded or has multiple patterns, move on to the next
1699
+ // condition, if there is any, rather than falling back to
1700
+ // the default.
1701
+ let guarded = m[ i] . data . arm . guard . is_some ( ) ;
1702
+ let multi_pats = m[ i] . pats . len ( ) > 1 ;
1703
+ if i+1 < len && ( guarded || multi_pats) {
1704
+ branch_chk = Some ( JumpToBasicBlock ( bcx. llbb ) ) ;
1705
+ }
1750
1706
CondBr ( after_cx, matches, opt_cx. llbb , bcx. llbb ) ;
1751
1707
}
1752
1708
compare_vec_len => {
@@ -1784,8 +1740,10 @@ fn compile_submatch_continue<'a, 'b>(
1784
1740
bcx = fcx. new_temp_block ( "compare_vec_len_next" ) ;
1785
1741
1786
1742
// If none of these subcases match, move on to the
1787
- // next condition.
1788
- branch_chk = Some ( JumpToBasicBlock ( bcx. llbb ) ) ;
1743
+ // next condition if there is any.
1744
+ if i+1 < len {
1745
+ branch_chk = Some ( JumpToBasicBlock ( bcx. llbb ) ) ;
1746
+ }
1789
1747
CondBr ( after_cx, matches, opt_cx. llbb , bcx. llbb ) ;
1790
1748
}
1791
1749
_ => ( )
@@ -1825,27 +1783,38 @@ fn compile_submatch_continue<'a, 'b>(
1825
1783
compile_submatch ( opt_cx,
1826
1784
opt_ms. as_slice ( ) ,
1827
1785
opt_vals. as_slice ( ) ,
1828
- chk)
1786
+ chk,
1787
+ has_genuine_default)
1829
1788
}
1830
1789
Some ( branch_chk) => {
1831
1790
compile_submatch ( opt_cx,
1832
1791
opt_ms. as_slice ( ) ,
1833
1792
opt_vals. as_slice ( ) ,
1834
- & branch_chk)
1793
+ & branch_chk,
1794
+ has_genuine_default)
1835
1795
}
1836
1796
}
1837
1797
}
1838
1798
1839
1799
// Compile the fall-through case, if any
1840
- if !exhaustive {
1800
+ if !exhaustive && kind != single {
1841
1801
if kind == compare || kind == compare_vec_len {
1842
1802
Br ( bcx, else_cx. llbb ) ;
1843
1803
}
1844
- if kind != single {
1845
- compile_submatch ( else_cx,
1846
- defaults. as_slice ( ) ,
1847
- vals_left. as_slice ( ) ,
1848
- chk) ;
1804
+ match chk {
1805
+ // If there is only one default arm left, move on to the next
1806
+ // condition explicitly rather than (eventually) falling back to
1807
+ // the last default arm.
1808
+ & JumpToBasicBlock ( _) if defaults. len ( ) == 1 && has_genuine_default => {
1809
+ Br ( else_cx, chk. handle_fail ( ) ) ;
1810
+ }
1811
+ _ => {
1812
+ compile_submatch ( else_cx,
1813
+ defaults. as_slice ( ) ,
1814
+ vals_left. as_slice ( ) ,
1815
+ chk,
1816
+ has_genuine_default) ;
1817
+ }
1849
1818
}
1850
1819
}
1851
1820
}
@@ -1950,7 +1919,22 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
1950
1919
} ) ) ;
1951
1920
}
1952
1921
1953
- compile_submatch ( bcx, matches. as_slice ( ) , [ discr_datum. val ] , & chk) ;
1922
+ // `compile_submatch` works one column of arm patterns a time and
1923
+ // then peels that column off. So as we progress, it may become
1924
+ // impossible to know whether we have a genuine default arm, i.e.
1925
+ // `_ => foo` or not. Sometimes it is important to know that in order
1926
+ // to decide whether moving on to the next condition or falling back
1927
+ // to the default arm.
1928
+ let has_default = arms. len ( ) > 0 && {
1929
+ let ref pats = arms. last ( ) . unwrap ( ) . pats ;
1930
+
1931
+ pats. len ( ) == 1
1932
+ && match pats. last ( ) . unwrap ( ) . node {
1933
+ ast:: PatWild => true , _ => false
1934
+ }
1935
+ } ;
1936
+
1937
+ compile_submatch ( bcx, matches. as_slice ( ) , [ discr_datum. val ] , & chk, has_default) ;
1954
1938
1955
1939
let mut arm_cxs = Vec :: new ( ) ;
1956
1940
for arm_data in arm_datas. iter ( ) {
0 commit comments