@@ -526,7 +526,7 @@ fn enter_default<'a, 'b>(
526
526
// Collect all of the matches that can match against anything.
527
527
let matches = enter_match ( bcx, dm, m, col, val, |p| {
528
528
match p. node {
529
- ast:: PatWild | ast:: PatWildMulti | ast :: PatTup ( _ ) => Some ( Vec :: new ( ) ) ,
529
+ ast:: PatWild | ast:: PatWildMulti => Some ( Vec :: new ( ) ) ,
530
530
ast:: PatIdent ( _, _, None ) if pat_is_binding ( dm, p) => Some ( Vec :: new ( ) ) ,
531
531
_ => None
532
532
}
@@ -712,18 +712,7 @@ fn enter_opt<'a, 'b>(
712
712
}
713
713
_ => {
714
714
assert_is_binding_or_wild ( bcx, p) ;
715
- // In most cases, a binding/wildcard match be
716
- // considered to match against any Opt. However, when
717
- // doing vector pattern matching, submatches are
718
- // considered even if the eventual match might be from
719
- // a different submatch. Thus, when a submatch fails
720
- // when doing a vector match, we proceed to the next
721
- // submatch. Thus, including a default match would
722
- // cause the default match to fire spuriously.
723
- match * opt {
724
- vec_len( ..) => None ,
725
- _ => Some ( Vec :: from_elem ( variant_size, dummy) )
726
- }
715
+ Some ( Vec :: from_elem ( variant_size, dummy) )
727
716
}
728
717
} ;
729
718
i += 1 ;
@@ -1363,7 +1352,8 @@ fn compile_guard<'a, 'b>(
1363
1352
data : & ArmData ,
1364
1353
m : & ' a [ Match < ' a , ' b > ] ,
1365
1354
vals : & [ ValueRef ] ,
1366
- chk : & FailureHandler )
1355
+ chk : & FailureHandler ,
1356
+ has_genuine_default : bool )
1367
1357
-> & ' b Block < ' b > {
1368
1358
debug ! ( "compile_guard(bcx={}, guard_expr={}, m={}, vals={})" ,
1369
1359
bcx. to_str( ) ,
@@ -1394,7 +1384,17 @@ fn compile_guard<'a, 'b>(
1394
1384
// Guard does not match: free the values we copied,
1395
1385
// and remove all bindings from the lllocals table
1396
1386
let bcx = drop_bindings ( bcx, data) ;
1397
- 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
+ } ;
1398
1398
bcx
1399
1399
} ) ;
1400
1400
@@ -1418,7 +1418,8 @@ fn compile_submatch<'a, 'b>(
1418
1418
bcx : & ' b Block < ' b > ,
1419
1419
m : & ' a [ Match < ' a , ' b > ] ,
1420
1420
vals : & [ ValueRef ] ,
1421
- chk : & FailureHandler ) {
1421
+ chk : & FailureHandler ,
1422
+ has_genuine_default : bool ) {
1422
1423
debug ! ( "compile_submatch(bcx={}, m={}, vals={})" ,
1423
1424
bcx. to_str( ) ,
1424
1425
m. repr( bcx. tcx( ) ) ,
@@ -1448,7 +1449,8 @@ fn compile_submatch<'a, 'b>(
1448
1449
m[ 0 ] . data ,
1449
1450
m. slice ( 1 , m. len ( ) ) ,
1450
1451
vals,
1451
- chk) ;
1452
+ chk,
1453
+ has_genuine_default) ;
1452
1454
}
1453
1455
_ => ( )
1454
1456
}
@@ -1466,9 +1468,10 @@ fn compile_submatch<'a, 'b>(
1466
1468
vals,
1467
1469
chk,
1468
1470
col,
1469
- val)
1471
+ val,
1472
+ has_genuine_default)
1470
1473
} else {
1471
- compile_submatch_continue ( bcx, m, vals, chk, col, val)
1474
+ compile_submatch_continue ( bcx, m, vals, chk, col, val, has_genuine_default )
1472
1475
}
1473
1476
}
1474
1477
@@ -1478,7 +1481,8 @@ fn compile_submatch_continue<'a, 'b>(
1478
1481
vals : & [ ValueRef ] ,
1479
1482
chk : & FailureHandler ,
1480
1483
col : uint ,
1481
- val : ValueRef ) {
1484
+ val : ValueRef ,
1485
+ has_genuine_default : bool ) {
1482
1486
let fcx = bcx. fcx ;
1483
1487
let tcx = bcx. tcx ( ) ;
1484
1488
let dm = & tcx. def_map ;
@@ -1512,7 +1516,7 @@ fn compile_submatch_continue<'a, 'b>(
1512
1516
rec_fields. as_slice ( ) ,
1513
1517
val) . as_slice ( ) ,
1514
1518
rec_vals. append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1515
- chk) ;
1519
+ chk, has_genuine_default ) ;
1516
1520
} ) ;
1517
1521
return ;
1518
1522
}
@@ -1537,7 +1541,7 @@ fn compile_submatch_continue<'a, 'b>(
1537
1541
val,
1538
1542
n_tup_elts) . as_slice ( ) ,
1539
1543
tup_vals. append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1540
- chk) ;
1544
+ chk, has_genuine_default ) ;
1541
1545
return ;
1542
1546
}
1543
1547
@@ -1562,7 +1566,7 @@ fn compile_submatch_continue<'a, 'b>(
1562
1566
enter_tuple_struct ( bcx, dm, m, col, val,
1563
1567
struct_element_count) . as_slice ( ) ,
1564
1568
llstructvals. append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1565
- chk) ;
1569
+ chk, has_genuine_default ) ;
1566
1570
return ;
1567
1571
}
1568
1572
@@ -1571,7 +1575,7 @@ fn compile_submatch_continue<'a, 'b>(
1571
1575
compile_submatch ( bcx,
1572
1576
enter_uniq ( bcx, dm, m, col, val) . as_slice ( ) ,
1573
1577
( vec ! ( llbox) ) . append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1574
- chk) ;
1578
+ chk, has_genuine_default ) ;
1575
1579
return ;
1576
1580
}
1577
1581
@@ -1580,7 +1584,7 @@ fn compile_submatch_continue<'a, 'b>(
1580
1584
compile_submatch ( bcx,
1581
1585
enter_region ( bcx, dm, m, col, val) . as_slice ( ) ,
1582
1586
( vec ! ( loaded_val) ) . append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1583
- chk) ;
1587
+ chk, has_genuine_default ) ;
1584
1588
return ;
1585
1589
}
1586
1590
@@ -1637,9 +1641,9 @@ fn compile_submatch_continue<'a, 'b>(
1637
1641
1638
1642
// Compile subtrees for each option
1639
1643
for ( i, opt) in opts. iter ( ) . enumerate ( ) {
1640
- // In some cases in vector pattern matching, we need to override
1641
- // the failure case so that instead of failing, it proceeds to
1642
- // 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
1643
1647
// for the current conditional branch.
1644
1648
let mut branch_chk = None ;
1645
1649
let mut opt_cx = else_cx;
@@ -1689,6 +1693,16 @@ fn compile_submatch_continue<'a, 'b>(
1689
1693
}
1690
1694
} ;
1691
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
+ }
1692
1706
CondBr ( after_cx, matches, opt_cx. llbb , bcx. llbb ) ;
1693
1707
}
1694
1708
compare_vec_len => {
@@ -1726,8 +1740,10 @@ fn compile_submatch_continue<'a, 'b>(
1726
1740
bcx = fcx. new_temp_block ( "compare_vec_len_next" ) ;
1727
1741
1728
1742
// If none of these subcases match, move on to the
1729
- // next condition.
1730
- 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
+ }
1731
1747
CondBr ( after_cx, matches, opt_cx. llbb , bcx. llbb ) ;
1732
1748
}
1733
1749
_ => ( )
@@ -1767,27 +1783,38 @@ fn compile_submatch_continue<'a, 'b>(
1767
1783
compile_submatch ( opt_cx,
1768
1784
opt_ms. as_slice ( ) ,
1769
1785
opt_vals. as_slice ( ) ,
1770
- chk)
1786
+ chk,
1787
+ has_genuine_default)
1771
1788
}
1772
1789
Some ( branch_chk) => {
1773
1790
compile_submatch ( opt_cx,
1774
1791
opt_ms. as_slice ( ) ,
1775
1792
opt_vals. as_slice ( ) ,
1776
- & branch_chk)
1793
+ & branch_chk,
1794
+ has_genuine_default)
1777
1795
}
1778
1796
}
1779
1797
}
1780
1798
1781
1799
// Compile the fall-through case, if any
1782
- if !exhaustive {
1800
+ if !exhaustive && kind != single {
1783
1801
if kind == compare || kind == compare_vec_len {
1784
1802
Br ( bcx, else_cx. llbb ) ;
1785
1803
}
1786
- if kind != single {
1787
- compile_submatch ( else_cx,
1788
- defaults. as_slice ( ) ,
1789
- vals_left. as_slice ( ) ,
1790
- 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
+ }
1791
1818
}
1792
1819
}
1793
1820
}
@@ -1892,7 +1919,22 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
1892
1919
} ) ) ;
1893
1920
}
1894
1921
1895
- 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) ;
1896
1938
1897
1939
let mut arm_cxs = Vec :: new ( ) ;
1898
1940
for arm_data in arm_datas. iter ( ) {
0 commit comments