@@ -289,42 +289,6 @@ fn opt_eq(tcx: &ty::ctxt, a: &Opt, b: &Opt) -> bool {
289289 }
290290}
291291
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-
328292pub enum opt_result < ' a > {
329293 single_result( Result < ' a > ) ,
330294 lower_bound( Result < ' a > ) ,
@@ -562,7 +526,7 @@ fn enter_default<'a, 'b>(
562526 // Collect all of the matches that can match against anything.
563527 let matches = enter_match ( bcx, dm, m, col, val, |p| {
564528 match p. node {
565- ast:: PatWild | ast:: PatWildMulti | ast :: PatTup ( _ ) => Some ( Vec :: new ( ) ) ,
529+ ast:: PatWild | ast:: PatWildMulti => Some ( Vec :: new ( ) ) ,
566530 ast:: PatIdent ( _, _, None ) if pat_is_binding ( dm, p) => Some ( Vec :: new ( ) ) ,
567531 _ => None
568532 }
@@ -634,30 +598,16 @@ fn enter_opt<'a, 'b>(
634598 let tcx = bcx. tcx ( ) ;
635599 let dummy = @ast:: Pat { id : 0 , node : ast:: PatWild , span : DUMMY_SP } ;
636600 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 ;
650601 enter_match ( bcx, & tcx. def_map , m, col, val, |p| {
651602 let answer = match p. node {
652603 ast:: PatEnum ( ..) |
653604 ast:: PatIdent ( _, _, None ) if pat_is_const ( & tcx. def_map , p) => {
654605 let const_def = tcx. def_map . borrow ( ) . get_copy ( & p. id ) ;
655606 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
661611 }
662612 }
663613 ast:: PatEnum ( _, ref subpats) => {
@@ -682,20 +632,12 @@ fn enter_opt<'a, 'b>(
682632 }
683633 }
684634 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 }
691637 }
692638 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 }
699641 }
700642 ast:: PatStruct ( _, ref field_pats, _) => {
701643 if opt_eq ( tcx, & variant_opt ( bcx, p. id ) , opt) {
@@ -770,18 +712,7 @@ fn enter_opt<'a, 'b>(
770712 }
771713 _ => {
772714 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) )
785716 }
786717 } ;
787718 i += 1 ;
@@ -1421,7 +1352,8 @@ fn compile_guard<'a, 'b>(
14211352 data : & ArmData ,
14221353 m : & ' a [ Match < ' a , ' b > ] ,
14231354 vals : & [ ValueRef ] ,
1424- chk : & FailureHandler )
1355+ chk : & FailureHandler ,
1356+ has_genuine_default : bool )
14251357 -> & ' b Block < ' b > {
14261358 debug ! ( "compile_guard(bcx={}, guard_expr={}, m={}, vals={})" ,
14271359 bcx. to_str( ) ,
@@ -1452,7 +1384,17 @@ fn compile_guard<'a, 'b>(
14521384 // Guard does not match: free the values we copied,
14531385 // and remove all bindings from the lllocals table
14541386 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+ } ;
14561398 bcx
14571399 } ) ;
14581400
@@ -1476,7 +1418,8 @@ fn compile_submatch<'a, 'b>(
14761418 bcx : & ' b Block < ' b > ,
14771419 m : & ' a [ Match < ' a , ' b > ] ,
14781420 vals : & [ ValueRef ] ,
1479- chk : & FailureHandler ) {
1421+ chk : & FailureHandler ,
1422+ has_genuine_default : bool ) {
14801423 debug ! ( "compile_submatch(bcx={}, m={}, vals={})" ,
14811424 bcx. to_str( ) ,
14821425 m. repr( bcx. tcx( ) ) ,
@@ -1506,7 +1449,8 @@ fn compile_submatch<'a, 'b>(
15061449 m[ 0 ] . data ,
15071450 m. slice ( 1 , m. len ( ) ) ,
15081451 vals,
1509- chk) ;
1452+ chk,
1453+ has_genuine_default) ;
15101454 }
15111455 _ => ( )
15121456 }
@@ -1524,9 +1468,10 @@ fn compile_submatch<'a, 'b>(
15241468 vals,
15251469 chk,
15261470 col,
1527- val)
1471+ val,
1472+ has_genuine_default)
15281473 } else {
1529- compile_submatch_continue ( bcx, m, vals, chk, col, val)
1474+ compile_submatch_continue ( bcx, m, vals, chk, col, val, has_genuine_default )
15301475 }
15311476}
15321477
@@ -1536,7 +1481,8 @@ fn compile_submatch_continue<'a, 'b>(
15361481 vals : & [ ValueRef ] ,
15371482 chk : & FailureHandler ,
15381483 col : uint ,
1539- val : ValueRef ) {
1484+ val : ValueRef ,
1485+ has_genuine_default : bool ) {
15401486 let fcx = bcx. fcx ;
15411487 let tcx = bcx. tcx ( ) ;
15421488 let dm = & tcx. def_map ;
@@ -1570,7 +1516,7 @@ fn compile_submatch_continue<'a, 'b>(
15701516 rec_fields. as_slice ( ) ,
15711517 val) . as_slice ( ) ,
15721518 rec_vals. append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1573- chk) ;
1519+ chk, has_genuine_default ) ;
15741520 } ) ;
15751521 return ;
15761522 }
@@ -1595,7 +1541,7 @@ fn compile_submatch_continue<'a, 'b>(
15951541 val,
15961542 n_tup_elts) . as_slice ( ) ,
15971543 tup_vals. append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1598- chk) ;
1544+ chk, has_genuine_default ) ;
15991545 return ;
16001546 }
16011547
@@ -1620,7 +1566,7 @@ fn compile_submatch_continue<'a, 'b>(
16201566 enter_tuple_struct ( bcx, dm, m, col, val,
16211567 struct_element_count) . as_slice ( ) ,
16221568 llstructvals. append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1623- chk) ;
1569+ chk, has_genuine_default ) ;
16241570 return ;
16251571 }
16261572
@@ -1629,7 +1575,7 @@ fn compile_submatch_continue<'a, 'b>(
16291575 compile_submatch ( bcx,
16301576 enter_uniq ( bcx, dm, m, col, val) . as_slice ( ) ,
16311577 ( vec ! ( llbox) ) . append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1632- chk) ;
1578+ chk, has_genuine_default ) ;
16331579 return ;
16341580 }
16351581
@@ -1638,7 +1584,7 @@ fn compile_submatch_continue<'a, 'b>(
16381584 compile_submatch ( bcx,
16391585 enter_region ( bcx, dm, m, col, val) . as_slice ( ) ,
16401586 ( vec ! ( loaded_val) ) . append ( vals_left. as_slice ( ) ) . as_slice ( ) ,
1641- chk) ;
1587+ chk, has_genuine_default ) ;
16421588 return ;
16431589 }
16441590
@@ -1695,9 +1641,9 @@ fn compile_submatch_continue<'a, 'b>(
16951641
16961642 // Compile subtrees for each option
16971643 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
17011647 // for the current conditional branch.
17021648 let mut branch_chk = None ;
17031649 let mut opt_cx = else_cx;
@@ -1747,6 +1693,16 @@ fn compile_submatch_continue<'a, 'b>(
17471693 }
17481694 } ;
17491695 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+ }
17501706 CondBr ( after_cx, matches, opt_cx. llbb , bcx. llbb ) ;
17511707 }
17521708 compare_vec_len => {
@@ -1784,8 +1740,10 @@ fn compile_submatch_continue<'a, 'b>(
17841740 bcx = fcx. new_temp_block ( "compare_vec_len_next" ) ;
17851741
17861742 // 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+ }
17891747 CondBr ( after_cx, matches, opt_cx. llbb , bcx. llbb ) ;
17901748 }
17911749 _ => ( )
@@ -1825,27 +1783,38 @@ fn compile_submatch_continue<'a, 'b>(
18251783 compile_submatch ( opt_cx,
18261784 opt_ms. as_slice ( ) ,
18271785 opt_vals. as_slice ( ) ,
1828- chk)
1786+ chk,
1787+ has_genuine_default)
18291788 }
18301789 Some ( branch_chk) => {
18311790 compile_submatch ( opt_cx,
18321791 opt_ms. as_slice ( ) ,
18331792 opt_vals. as_slice ( ) ,
1834- & branch_chk)
1793+ & branch_chk,
1794+ has_genuine_default)
18351795 }
18361796 }
18371797 }
18381798
18391799 // Compile the fall-through case, if any
1840- if !exhaustive {
1800+ if !exhaustive && kind != single {
18411801 if kind == compare || kind == compare_vec_len {
18421802 Br ( bcx, else_cx. llbb ) ;
18431803 }
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+ }
18491818 }
18501819 }
18511820}
@@ -1950,7 +1919,22 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
19501919 } ) ) ;
19511920 }
19521921
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) ;
19541938
19551939 let mut arm_cxs = Vec :: new ( ) ;
19561940 for arm_data in arm_datas. iter ( ) {
0 commit comments