@@ -354,10 +354,10 @@ fn pick_col(m: match) -> uint {
354
354
ret best_col;
355
355
}
356
356
357
- fn compile_submatch ( bcx : block , m : match , vals : [ ValueRef ] , f : mk_fail ,
358
- & exits: [ exit_node ] ) {
357
+ fn compile_submatch ( bcx : block , m : match , vals : [ ValueRef ] ,
358
+ chk : option < mk_fail > , & exits: [ exit_node ] ) {
359
359
let bcx = bcx, tcx = bcx. tcx ( ) , dm = tcx. def_map ;
360
- if m. len ( ) == 0 u { Br ( bcx, f ( ) ) ; ret; }
360
+ if m. len ( ) == 0 u { Br ( bcx, option :: get ( chk ) ( ) ) ; ret; }
361
361
if m[ 0 ] . pats . len ( ) == 0 u {
362
362
let data = m[ 0 ] . data ;
363
363
alt data. guard {
@@ -372,7 +372,7 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
372
372
trans_temp_expr ( bcx, e)
373
373
} ;
374
374
bcx = with_cond ( guard_cx, Not ( guard_cx, val) ) { |bcx|
375
- compile_submatch ( bcx, vec:: tail ( m) , vals, f , exits) ;
375
+ compile_submatch ( bcx, vec:: tail ( m) , vals, chk , exits) ;
376
376
bcx
377
377
} ;
378
378
}
@@ -389,13 +389,10 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
389
389
let val = vals[ col] ;
390
390
let m = if has_nested_bindings ( m, col) {
391
391
expand_nested_bindings ( m, col, val)
392
- } else {
393
- m
394
- } ;
392
+ } else { m } ;
395
393
396
- let vals_left =
397
- vec:: slice ( vals, 0 u, col) +
398
- vec:: slice ( vals, col + 1 u, vals. len ( ) ) ;
394
+ let vals_left = vec:: slice ( vals, 0 u, col) +
395
+ vec:: slice ( vals, col + 1 u, vals. len ( ) ) ;
399
396
let ccx = bcx. fcx . ccx ;
400
397
let pat_id = 0 ;
401
398
for br: match_branch in m {
@@ -417,7 +414,7 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
417
414
bcx = r. bcx ;
418
415
}
419
416
compile_submatch ( bcx, enter_rec ( dm, m, col, rec_fields, val) ,
420
- rec_vals + vals_left, f , exits) ;
417
+ rec_vals + vals_left, chk , exits) ;
421
418
ret;
422
419
}
423
420
@@ -435,7 +432,7 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
435
432
i += 1 u;
436
433
}
437
434
compile_submatch ( bcx, enter_tup ( dm, m, col, val, n_tup_elts) ,
438
- tup_vals + vals_left, f , exits) ;
435
+ tup_vals + vals_left, chk , exits) ;
439
436
ret;
440
437
}
441
438
@@ -444,14 +441,14 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
444
441
let box = Load ( bcx, val) ;
445
442
let unboxed = GEPi ( bcx, box, [ 0 , abi:: box_field_body] ) ;
446
443
compile_submatch ( bcx, enter_box ( dm, m, col, val) , [ unboxed]
447
- + vals_left, f , exits) ;
444
+ + vals_left, chk , exits) ;
448
445
ret;
449
446
}
450
447
451
448
if any_uniq_pat ( m, col) {
452
449
let unboxed = Load ( bcx, val) ;
453
450
compile_submatch ( bcx, enter_uniq ( dm, m, col, val) ,
454
- [ unboxed] + vals_left, f , exits) ;
451
+ [ unboxed] + vals_left, chk , exits) ;
455
452
ret;
456
453
}
457
454
@@ -499,42 +496,48 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
499
496
Switch ( bcx, test_val, else_cx. llbb , opts. len ( ) )
500
497
} else { C_int ( ccx, 0 ) } ; // Placeholder for when not using a switch
501
498
502
- // Compile subtrees for each option
503
- for opt: opt in opts {
504
- let opt_cx = sub_block ( bcx, "match_case" ) ;
505
- alt kind {
506
- single { Br ( bcx, opt_cx. llbb ) ; }
507
- switch {
508
- let res = trans_opt ( bcx, opt) ;
509
- alt check res {
510
- single_result( r) {
511
- llvm:: LLVMAddCase ( sw, r. val , opt_cx. llbb ) ;
512
- bcx = r. bcx ;
513
- }
514
- }
515
- }
516
- compare {
517
- let t = node_id_type ( bcx, pat_id) ;
518
- let { bcx: after_cx , val: matches} =
519
- with_scope_result ( bcx, "compare_scope" ) { |bcx|
520
- alt trans_opt ( bcx, opt) {
521
- single_result ( { bcx, val} ) {
522
- trans_compare ( bcx, ast:: eq, test_val, t, val, t)
523
- }
524
- range_result ( { val: vbegin, _} , { bcx, val: vend} ) {
525
- let { bcx, val: ge } = trans_compare ( bcx, ast:: ge, test_val,
526
- t, vbegin, t) ;
527
- let { bcx, val: le } = trans_compare ( bcx, ast:: le, test_val,
528
- t, vend, t) ;
529
- { bcx: bcx, val: And ( bcx, ge, le) }
499
+ let defaults = enter_default ( dm, m, col, val) ;
500
+ let exhaustive = option:: is_none ( chk) && defaults. len ( ) == 0 u;
501
+ let len = opts. len ( ) , i = 0 u;
502
+ // Compile subtrees for each option
503
+ for opt in opts {
504
+ i += 1 u;
505
+ let opt_cx = else_cx;
506
+ if !exhaustive || i < len {
507
+ opt_cx = sub_block ( bcx, "match_case" ) ;
508
+ alt kind {
509
+ single { Br ( bcx, opt_cx. llbb ) ; }
510
+ switch {
511
+ alt check trans_opt( bcx, opt) {
512
+ single_result( r) {
513
+ llvm:: LLVMAddCase ( sw, r. val , opt_cx. llbb ) ;
514
+ bcx = r. bcx ;
530
515
}
531
516
}
532
- } ;
533
- bcx = sub_block ( after_cx, "compare_next" ) ;
534
- CondBr ( after_cx, matches, opt_cx. llbb , bcx. llbb ) ;
535
- }
536
- _ { }
537
- }
517
+ }
518
+ compare {
519
+ let t = node_id_type ( bcx, pat_id) ;
520
+ let { bcx: after_cx , val: matches} =
521
+ with_scope_result ( bcx, "compare_scope" ) { |bcx|
522
+ alt trans_opt ( bcx, opt) {
523
+ single_result ( { bcx, val} ) {
524
+ trans_compare ( bcx, ast:: eq, test_val, t, val, t)
525
+ }
526
+ range_result ( { val: vbegin, _} , { bcx, val: vend} ) {
527
+ let { bcx, val: ge } = trans_compare (
528
+ bcx, ast:: ge, test_val, t, vbegin, t) ;
529
+ let { bcx, val: le } = trans_compare (
530
+ bcx, ast:: le, test_val, t, vend, t) ;
531
+ { bcx: bcx, val: And ( bcx, ge, le) }
532
+ }
533
+ }
534
+ } ;
535
+ bcx = sub_block ( after_cx, "compare_next" ) ;
536
+ CondBr ( after_cx, matches, opt_cx. llbb , bcx. llbb ) ;
537
+ }
538
+ _ { }
539
+ }
540
+ } else if kind == compare { Br ( bcx, else_cx. llbb ) ; }
538
541
let size = 0 u;
539
542
let unpacked = [ ] ;
540
543
alt opt {
@@ -547,14 +550,15 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
547
550
lit ( _) | range ( _, _) { }
548
551
}
549
552
compile_submatch ( opt_cx, enter_opt ( tcx, m, opt, col, size, val) ,
550
- unpacked + vals_left, f , exits) ;
553
+ unpacked + vals_left, chk , exits) ;
551
554
}
552
555
553
- // Compile the fall-through case
554
- if kind == compare { Br ( bcx, else_cx. llbb ) ; }
555
- if kind != single {
556
- compile_submatch ( else_cx, enter_default ( dm, m, col, val) , vals_left,
557
- f, exits) ;
556
+ // Compile the fall-through case, if any
557
+ if !exhaustive {
558
+ if kind == compare { Br ( bcx, else_cx. llbb ) ; }
559
+ if kind != single {
560
+ compile_submatch ( else_cx, defaults, vals_left, chk, exits) ;
561
+ }
558
562
}
559
563
}
560
564
@@ -605,12 +609,14 @@ fn make_phi_bindings(bcx: block, map: [exit_node],
605
609
}
606
610
607
611
fn trans_alt ( bcx : block , expr : @ast:: expr , arms : [ ast:: arm ] ,
608
- dest : dest ) -> block {
609
- with_scope ( bcx, "alt" ) { |bcx| trans_alt_inner ( bcx, expr, arms, dest) }
612
+ mode : ast:: alt_mode , dest : dest ) -> block {
613
+ with_scope ( bcx, "alt" ) { |bcx|
614
+ trans_alt_inner ( bcx, expr, arms, mode, dest)
615
+ }
610
616
}
611
617
612
618
fn trans_alt_inner ( scope_cx : block , expr : @ast:: expr , arms : [ ast:: arm ] ,
613
- dest : dest ) -> block {
619
+ mode : ast :: alt_mode , dest : dest ) -> block {
614
620
let bcx = scope_cx, tcx = bcx. tcx ( ) ;
615
621
let bodies = [ ] , match = [ ] ;
616
622
@@ -630,22 +636,26 @@ fn trans_alt_inner(scope_cx: block, expr: @ast::expr, arms: [ast::arm],
630
636
}
631
637
}
632
638
633
- // Cached fail-on-fallthrough block
634
- let fail_cx = @mutable none;
635
- fn mk_fail ( bcx : block , sp : span ,
636
- done : @mutable option < BasicBlockRef > ) -> BasicBlockRef {
637
- alt * done { some( bb) { ret bb; } _ { } }
638
- let fail_cx = sub_block ( bcx, "case_fallthrough" ) ;
639
- trans_fail ( fail_cx, some ( sp) , "non-exhaustive match failure" ) ; ;
640
- * done = some ( fail_cx. llbb ) ;
641
- ret fail_cx. llbb ;
642
- }
643
-
639
+ let mk_fail = alt mode {
640
+ ast : : alt_check {
641
+ // Cached fail-on-fallthrough block
642
+ let fail_cx = @mutable none;
643
+ fn mk_fail( bcx : block, sp : span,
644
+ done : @mutable option<BasicBlockRef >) -> BasicBlockRef {
645
+ alt * done { some( bb) { ret bb; } _ { } }
646
+ let fail_cx = sub_block ( bcx, "case_fallthrough" ) ;
647
+ trans_fail ( fail_cx, some ( sp) , "non-exhaustive match failure" ) ; ;
648
+ * done = some ( fail_cx. llbb ) ;
649
+ ret fail_cx. llbb ;
650
+ }
651
+ some( bind mk_fail ( scope_cx, expr. span , fail_cx) )
652
+ }
653
+ ast:: alt_exhaustive { none }
654
+ } ;
644
655
let exit_map = [ ] ;
645
656
let t = node_id_type ( bcx, expr. id ) ;
646
657
let { bcx, val: spilled } = spill_if_immediate ( bcx, val, t) ;
647
- compile_submatch ( bcx, match , [ spilled] ,
648
- bind mk_fail ( scope_cx, expr. span , fail_cx) , exit_map) ;
658
+ compile_submatch ( bcx, match , [ spilled] , mk_fail, exit_map) ;
649
659
650
660
let arm_cxs = [ ] , arm_dests = [ ] , i = 0 u;
651
661
for a in arms {
0 commit comments