@@ -20,7 +20,7 @@ use util::ppaux::ty_to_str;
20
20
use std:: cmp;
21
21
use std:: iter;
22
22
use syntax:: ast:: * ;
23
- use syntax:: ast_util:: { unguarded_pat , walk_pat} ;
23
+ use syntax:: ast_util:: { is_unguarded , walk_pat} ;
24
24
use syntax:: codemap:: { DUMMY_SP , Span } ;
25
25
use syntax:: parse:: token;
26
26
use syntax:: visit;
@@ -79,26 +79,13 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
79
79
// If the type *is* empty, it's vacuously exhaustive
80
80
return ;
81
81
}
82
- match ty:: get ( pat_ty) . sty {
83
- ty_enum( did, _) => {
84
- if ( * enum_variants ( cx. tcx , did) ) . is_empty ( ) &&
85
- ( * arms) . is_empty ( ) {
86
-
87
- return ;
88
- }
89
- }
90
- _ => { /* We assume only enum types can be uninhabited */ }
91
- }
92
-
93
- let pats: Vec < @Pat > = arms. iter ( )
94
- . filter_map ( unguarded_pat)
95
- . flat_map ( |pats| pats. move_iter ( ) )
96
- . collect ( ) ;
97
- if pats. is_empty ( ) {
98
- cx. tcx . sess . span_err ( ex. span , "non-exhaustive patterns" ) ;
99
- } else {
100
- check_exhaustive ( cx, ex. span , pats) ;
101
- }
82
+ let m: matrix = arms
83
+ . iter ( )
84
+ . filter ( |& arm| is_unguarded ( arm) )
85
+ . flat_map ( |arm| arm. pats . iter ( ) )
86
+ . map ( |pat| vec ! ( pat. clone( ) ) )
87
+ . collect ( ) ;
88
+ check_exhaustive ( cx, ex. span , & m) ;
102
89
}
103
90
_ => ( )
104
91
}
@@ -152,9 +139,8 @@ fn raw_pat(p: @Pat) -> @Pat {
152
139
}
153
140
}
154
141
155
- fn check_exhaustive ( cx : & MatchCheckCtxt , sp : Span , pats : Vec < @Pat > ) {
156
- assert ! ( ( !pats. is_empty( ) ) ) ;
157
- let ext = match is_useful ( cx, & pats. iter ( ) . map ( |p| vec ! ( * p) ) . collect ( ) , [ wild ( ) ] ) {
142
+ fn check_exhaustive ( cx : & MatchCheckCtxt , sp : Span , m : & matrix ) {
143
+ let ext = match is_useful ( cx, m, [ wild ( ) ] ) {
158
144
not_useful => {
159
145
// This is good, wildcard pattern isn't reachable
160
146
return ;
@@ -587,23 +573,20 @@ fn specialize(cx: &MatchCheckCtxt,
587
573
arity : uint ,
588
574
left_ty : ty:: t )
589
575
-> Option < Vec < @Pat > > {
590
- // Sad, but I can't get rid of this easily
591
- let r0 = ( * raw_pat ( r[ 0 ] ) ) . clone ( ) ;
592
- match r0 {
593
- Pat { id : pat_id, node : n, span : pat_span} =>
594
- match n {
595
- PatWild => {
596
- Some ( Vec :: from_elem ( arity, wild ( ) ) . append ( r. tail ( ) ) )
576
+ let & Pat { id : ref pat_id, node : ref n, span : ref pat_span} = & ( * raw_pat ( r[ 0 ] ) ) ;
577
+ let head: Option < Vec < @Pat > > = match n {
578
+ & PatWild => {
579
+ Some ( Vec :: from_elem ( arity, wild ( ) ) )
597
580
}
598
- PatWildMulti => {
599
- Some ( Vec :: from_elem ( arity, wild_multi ( ) ) . append ( r . tail ( ) ) )
581
+ & PatWildMulti => {
582
+ Some ( Vec :: from_elem ( arity, wild_multi ( ) ) )
600
583
}
601
- PatIdent ( _, _, _) => {
602
- let opt_def = cx. tcx . def_map . borrow ( ) . find_copy ( & pat_id) ;
584
+ & PatIdent ( _, _, _) => {
585
+ let opt_def = cx. tcx . def_map . borrow ( ) . find_copy ( pat_id) ;
603
586
match opt_def {
604
587
Some ( DefVariant ( _, id, _) ) => {
605
588
if variant ( id) == * ctor_id {
606
- Some ( Vec :: from_slice ( r . tail ( ) ) )
589
+ Some ( vec ! ( ) )
607
590
} else {
608
591
None
609
592
}
@@ -617,7 +600,7 @@ fn specialize(cx: &MatchCheckCtxt,
617
600
match compare_const_vals ( & e_v, v) {
618
601
Some ( val1) => ( val1 == 0 ) ,
619
602
None => {
620
- cx. tcx . sess . span_err ( pat_span,
603
+ cx. tcx . sess . span_err ( * pat_span,
621
604
"mismatched types between arms" ) ;
622
605
false
623
606
}
@@ -631,7 +614,7 @@ fn specialize(cx: &MatchCheckCtxt,
631
614
( val1 >= 0 && val2 <= 0 )
632
615
}
633
616
_ => {
634
- cx. tcx . sess . span_err ( pat_span,
617
+ cx. tcx . sess . span_err ( * pat_span,
635
618
"mismatched types between ranges" ) ;
636
619
false
637
620
}
@@ -641,18 +624,18 @@ fn specialize(cx: &MatchCheckCtxt,
641
624
_ => fail ! ( "type error" )
642
625
} ;
643
626
if match_ {
644
- Some ( Vec :: from_slice ( r . tail ( ) ) )
627
+ Some ( vec ! ( ) )
645
628
} else {
646
629
None
647
630
}
648
631
}
649
632
_ => {
650
- Some ( Vec :: from_elem ( arity, wild ( ) ) . append ( r . tail ( ) ) )
633
+ Some ( Vec :: from_elem ( arity, wild ( ) ) )
651
634
}
652
635
}
653
636
}
654
- PatEnum ( _, args) => {
655
- let def = cx. tcx . def_map . borrow ( ) . get_copy ( & pat_id) ;
637
+ & PatEnum ( _, ref args) => {
638
+ let def = cx. tcx . def_map . borrow ( ) . get_copy ( pat_id) ;
656
639
match def {
657
640
DefStatic ( did, _) => {
658
641
let const_expr =
@@ -663,7 +646,7 @@ fn specialize(cx: &MatchCheckCtxt,
663
646
match compare_const_vals ( & e_v, v) {
664
647
Some ( val1) => ( val1 == 0 ) ,
665
648
None => {
666
- cx. tcx . sess . span_err ( pat_span,
649
+ cx. tcx . sess . span_err ( * pat_span,
667
650
"mismatched types between arms" ) ;
668
651
false
669
652
}
@@ -674,7 +657,7 @@ fn specialize(cx: &MatchCheckCtxt,
674
657
match ( m1, m2) {
675
658
( Some ( val1) , Some ( val2) ) => ( val1 >= 0 && val2 <= 0 ) ,
676
659
_ => {
677
- cx. tcx . sess . span_err ( pat_span,
660
+ cx. tcx . sess . span_err ( * pat_span,
678
661
"mismatched types between ranges" ) ;
679
662
false
680
663
}
@@ -684,97 +667,72 @@ fn specialize(cx: &MatchCheckCtxt,
684
667
_ => fail ! ( "type error" )
685
668
} ;
686
669
if match_ {
687
- Some ( Vec :: from_slice ( r . tail ( ) ) )
670
+ Some ( vec ! ( ) )
688
671
} else {
689
672
None
690
673
}
691
674
}
692
- DefVariant ( _, id, _) if variant ( id) == * ctor_id => {
693
- let args = match args {
694
- Some ( args) => args. iter ( ) . map ( |x| * x) . collect ( ) ,
695
- None => Vec :: from_elem ( arity, wild ( ) )
696
- } ;
697
- Some ( args. append ( r. tail ( ) ) )
698
- }
699
- DefVariant ( _, _, _) => None ,
700
-
701
- DefFn ( ..) |
702
- DefStruct ( ..) => {
703
- let new_args;
704
- match args {
705
- Some ( args) => {
706
- new_args = args. iter ( ) . map ( |x| * x) . collect ( )
707
- }
708
- None => new_args = Vec :: from_elem ( arity, wild ( ) )
709
- }
710
- Some ( new_args. append ( r. tail ( ) ) )
675
+ DefVariant ( _, id, _) if variant ( id) != * ctor_id => None ,
676
+ DefVariant ( ..) | DefFn ( ..) | DefStruct ( ..) => {
677
+ Some ( match args {
678
+ & Some ( ref args) => args. clone ( ) ,
679
+ & None => Vec :: from_elem ( arity, wild ( ) )
680
+ } )
711
681
}
712
682
_ => None
713
683
}
714
684
}
715
- PatStruct ( _, ref pattern_fields, _) => {
685
+ & PatStruct ( _, ref pattern_fields, _) => {
716
686
// Is this a struct or an enum variant?
717
- let def = cx. tcx . def_map . borrow ( ) . get_copy ( & pat_id) ;
718
- match def {
687
+ let def = cx. tcx . def_map . borrow ( ) . get_copy ( pat_id) ;
688
+ let class_id = match def {
719
689
DefVariant ( _, variant_id, _) => {
720
- if variant ( variant_id) == * ctor_id {
721
- let struct_fields = ty:: lookup_struct_fields ( cx. tcx , variant_id) ;
722
- let args = struct_fields. iter ( ) . map ( |sf| {
723
- match pattern_fields. iter ( ) . find ( |f| f. ident . name == sf. name ) {
724
- Some ( f) => f. pat ,
725
- _ => wild ( )
726
- }
727
- } ) . collect :: < Vec < _ > > ( ) ;
728
- Some ( args. append ( r. tail ( ) ) )
729
- } else {
730
- None
731
- }
690
+ if variant ( variant_id) == * ctor_id {
691
+ Some ( variant_id)
692
+ } else {
693
+ None
694
+ }
732
695
}
733
696
_ => {
734
- // Grab the class data that we care about.
735
- let class_fields;
736
- let class_id;
737
697
match ty:: get ( left_ty) . sty {
738
- ty:: ty_struct( cid, _) => {
739
- class_id = cid;
740
- class_fields =
741
- ty:: lookup_struct_fields ( cx. tcx ,
742
- class_id) ;
743
- }
698
+ ty:: ty_struct( cid, _) => Some ( cid) ,
744
699
_ => {
745
700
cx. tcx . sess . span_bug (
746
- pat_span,
701
+ * pat_span,
747
702
format ! ( "struct pattern resolved to {}, \
748
703
not a struct",
749
704
ty_to_str( cx. tcx,
750
705
left_ty) ) . as_slice ( ) ) ;
751
706
}
752
707
}
753
- let args = class_fields. iter ( ) . map ( |class_field| {
754
- match pattern_fields. iter ( ) . find ( |f|
755
- f. ident . name == class_field. name ) {
756
- Some ( f) => f. pat ,
757
- _ => wild ( )
758
- }
759
- } ) . collect :: < Vec < _ > > ( ) ;
760
- Some ( args. append ( r. tail ( ) ) )
761
708
}
762
- }
709
+ } ;
710
+ class_id. map ( |variant_id| {
711
+ let struct_fields = ty:: lookup_struct_fields ( cx. tcx , variant_id) ;
712
+ let args = struct_fields. iter ( ) . map ( |sf| {
713
+ match pattern_fields. iter ( ) . find ( |f| f. ident . name == sf. name ) {
714
+ Some ( f) => f. pat ,
715
+ _ => wild ( )
716
+ }
717
+ } ) . collect ( ) ;
718
+ args
719
+ } )
720
+
763
721
}
764
- PatTup ( args) => {
765
- Some ( args. iter ( ) . map ( |x| * x) . collect :: < Vec < _ > > ( ) . append ( r . tail ( ) ) )
722
+ & PatTup ( ref args) => {
723
+ Some ( args. iter ( ) . map ( |x| * x) . collect ( ) )
766
724
}
767
- PatBox ( a ) | PatRegion ( a ) => {
768
- Some ( ( vec ! ( a ) ) . append ( r . tail ( ) ) )
725
+ & PatBox ( ref inner ) | & PatRegion ( ref inner ) => {
726
+ Some ( vec ! ( inner . clone ( ) ) )
769
727
}
770
- PatLit ( expr) => {
771
- let e_v = eval_const_expr ( cx. tcx , expr) ;
728
+ & PatLit ( ref expr) => {
729
+ let e_v = eval_const_expr ( cx. tcx , * expr) ;
772
730
let match_ = match * ctor_id {
773
731
val( ref v) => {
774
732
match compare_const_vals ( & e_v, v) {
775
733
Some ( val1) => val1 == 0 ,
776
734
None => {
777
- cx. tcx . sess . span_err ( pat_span,
735
+ cx. tcx . sess . span_err ( * pat_span,
778
736
"mismatched types between arms" ) ;
779
737
false
780
738
}
@@ -786,7 +744,7 @@ fn specialize(cx: &MatchCheckCtxt,
786
744
match ( m1, m2) {
787
745
( Some ( val1) , Some ( val2) ) => ( val1 >= 0 && val2 <= 0 ) ,
788
746
_ => {
789
- cx. tcx . sess . span_err ( pat_span,
747
+ cx. tcx . sess . span_err ( * pat_span,
790
748
"mismatched types between ranges" ) ;
791
749
false
792
750
}
@@ -796,52 +754,49 @@ fn specialize(cx: &MatchCheckCtxt,
796
754
_ => fail ! ( "type error" )
797
755
} ;
798
756
if match_ {
799
- Some ( Vec :: from_slice ( r . tail ( ) ) )
757
+ Some ( vec ! ( ) )
800
758
} else {
801
759
None
802
760
}
803
761
}
804
- PatRange ( lo, hi) => {
762
+ & PatRange ( lo, hi) => {
805
763
let ( c_lo, c_hi) = match * ctor_id {
806
- val( ref v) => ( ( * v ) . clone ( ) , ( * v ) . clone ( ) ) ,
807
- range( ref lo, ref hi) => ( ( * lo ) . clone ( ) , ( * hi ) . clone ( ) ) ,
808
- single => return Some ( Vec :: from_slice ( r . tail ( ) ) ) ,
764
+ val( ref v) => ( v , v ) ,
765
+ range( ref lo, ref hi) => ( lo , hi ) ,
766
+ single => return Some ( vec ! ( ) ) ,
809
767
_ => fail ! ( "type error" )
810
768
} ;
811
769
let v_lo = eval_const_expr ( cx. tcx , lo) ;
812
770
let v_hi = eval_const_expr ( cx. tcx , hi) ;
813
771
814
- let m1 = compare_const_vals ( & c_lo, & v_lo) ;
815
- let m2 = compare_const_vals ( & c_hi, & v_hi) ;
772
+ let m1 = compare_const_vals ( c_lo, & v_lo) ;
773
+ let m2 = compare_const_vals ( c_hi, & v_hi) ;
816
774
match ( m1, m2) {
817
775
( Some ( val1) , Some ( val2) ) if val1 >= 0 && val2 <= 0 => {
818
- Some ( Vec :: from_slice ( r . tail ( ) ) )
776
+ Some ( vec ! ( ) )
819
777
} ,
820
778
( Some ( _) , Some ( _) ) => None ,
821
779
_ => {
822
- cx. tcx . sess . span_err ( pat_span,
780
+ cx. tcx . sess . span_err ( * pat_span,
823
781
"mismatched types between ranges" ) ;
824
782
None
825
783
}
826
784
}
827
785
}
828
- PatVec ( before, slice, after) => {
786
+ & PatVec ( ref before, ref slice, ref after) => {
829
787
match * ctor_id {
830
788
vec( _) => {
831
789
let num_elements = before. len ( ) + after. len ( ) ;
832
790
if num_elements < arity && slice. is_some ( ) {
833
791
let mut result = Vec :: new ( ) ;
834
- let wilds = Vec :: from_elem ( arity - num_elements, wild ( ) ) ;
835
- result. push_all_move ( before) ;
836
- result. push_all_move ( wilds) ;
837
- result. push_all_move ( after) ;
838
- result. push_all ( r. tail ( ) ) ;
792
+ result. push_all ( before. as_slice ( ) ) ;
793
+ result. grow_fn ( arity - num_elements, |_| wild ( ) ) ;
794
+ result. push_all ( after. as_slice ( ) ) ;
839
795
Some ( result)
840
796
} else if num_elements == arity {
841
797
let mut result = Vec :: new ( ) ;
842
- result. push_all_move ( before) ;
843
- result. push_all_move ( after) ;
844
- result. push_all ( r. tail ( ) ) ;
798
+ result. push_all ( before. as_slice ( ) ) ;
799
+ result. push_all ( after. as_slice ( ) ) ;
845
800
Some ( result)
846
801
} else {
847
802
None
@@ -850,12 +805,12 @@ fn specialize(cx: &MatchCheckCtxt,
850
805
_ => None
851
806
}
852
807
}
853
- PatMac ( _) => {
854
- cx. tcx . sess . span_err ( pat_span, "unexpanded macro" ) ;
808
+ & PatMac ( _) => {
809
+ cx. tcx . sess . span_err ( * pat_span, "unexpanded macro" ) ;
855
810
None
856
811
}
857
- }
858
- }
812
+ } ;
813
+ head . map ( |head| head . append ( r . tail ( ) ) )
859
814
}
860
815
861
816
fn default ( cx : & MatchCheckCtxt , r : & [ @Pat ] ) -> Option < Vec < @Pat > > {
0 commit comments