@@ -24,7 +24,7 @@ use pattern::{FieldPattern, Pattern, PatternKind};
24
24
use pattern:: { PatternFoldable , PatternFolder } ;
25
25
26
26
use rustc:: hir:: def_id:: DefId ;
27
- use rustc:: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
27
+ use rustc:: ty:: { self , AdtKind , Ty , TyCtxt , TypeFoldable } ;
28
28
29
29
use rustc:: mir:: Field ;
30
30
use rustc:: util:: common:: ErrorReported ;
@@ -153,9 +153,6 @@ pub struct MatchCheckCtxt<'a, 'tcx: 'a> {
153
153
/// can not be seen to be empty outside it's module and should not
154
154
/// be matchable with an empty match statement.
155
155
pub node : NodeId ,
156
- /// A wild pattern with an error type - it exists to avoid having to normalize
157
- /// associated types to get field types.
158
- pub wild_pattern : & ' a Pattern < ' tcx > ,
159
156
pub pattern_arena : & ' a TypedArena < Pattern < ' tcx > > ,
160
157
pub byte_array_map : FxHashMap < * const Pattern < ' tcx > , Vec < & ' a Pattern < ' tcx > > > ,
161
158
}
@@ -167,25 +164,20 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
167
164
f : F ) -> R
168
165
where F : for < ' b > FnOnce ( MatchCheckCtxt < ' b , ' tcx > ) -> R
169
166
{
170
- let wild_pattern = Pattern {
171
- ty : tcx. types . err ,
172
- span : DUMMY_SP ,
173
- kind : box PatternKind :: Wild
174
- } ;
175
-
176
167
let pattern_arena = TypedArena :: new ( ) ;
177
168
178
169
f ( MatchCheckCtxt {
179
170
tcx : tcx,
180
171
node : node,
181
- wild_pattern : & wild_pattern,
182
172
pattern_arena : & pattern_arena,
183
173
byte_array_map : FxHashMap ( ) ,
184
174
} )
185
175
}
186
176
187
177
// convert a byte-string pattern to a list of u8 patterns.
188
- fn lower_byte_str_pattern ( & mut self , pat : & ' a Pattern < ' tcx > ) -> Vec < & ' a Pattern < ' tcx > > {
178
+ fn lower_byte_str_pattern < ' p > ( & mut self , pat : & ' p Pattern < ' tcx > ) -> Vec < & ' p Pattern < ' tcx > >
179
+ where ' a : ' p
180
+ {
189
181
let pattern_arena = & * self . pattern_arena ;
190
182
let tcx = self . tcx ;
191
183
self . byte_array_map . entry ( pat) . or_insert_with ( || {
@@ -401,6 +393,7 @@ fn missing_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
401
393
fn all_constructors < ' a , ' tcx : ' a > ( cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
402
394
pcx : PatternContext < ' tcx > ) -> Vec < Constructor >
403
395
{
396
+ debug ! ( "all_constructors({:?})" , pcx. ty) ;
404
397
match pcx. ty . sty {
405
398
ty:: TyBool =>
406
399
[ true , false ] . iter ( ) . map ( |b| ConstantValue ( ConstVal :: Bool ( * b) ) ) . collect ( ) ,
@@ -421,7 +414,10 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
421
414
ty:: TyAdt ( def, substs) if def. is_enum ( ) && def. variants . len ( ) != 1 => {
422
415
def. variants . iter ( ) . filter_map ( |v| {
423
416
let mut visited = FxHashSet :: default ( ) ;
424
- if v. is_uninhabited_recurse ( & mut visited, Some ( cx. node ) , cx. tcx , substs, false ) {
417
+ if v. is_uninhabited_recurse ( & mut visited,
418
+ Some ( cx. node ) ,
419
+ cx. tcx , substs,
420
+ AdtKind :: Enum ) {
425
421
None
426
422
} else {
427
423
Some ( Variant ( v. did ) )
@@ -438,10 +434,10 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
438
434
}
439
435
}
440
436
441
- fn max_slice_length < ' a , ' tcx , I > (
437
+ fn max_slice_length < ' p , ' a : ' p , ' tcx : ' a , I > (
442
438
_cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
443
439
patterns : I ) -> usize
444
- where I : Iterator < Item =& ' a Pattern < ' tcx > >
440
+ where I : Iterator < Item =& ' p Pattern < ' tcx > >
445
441
{
446
442
// The exhaustiveness-checking paper does not include any details on
447
443
// checking variable-length slice patterns. However, they are matched
@@ -532,6 +528,12 @@ fn max_slice_length<'a, 'tcx, I>(
532
528
}
533
529
534
530
/// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html
531
+ /// The algorithm from the paper has been modified to correctly handle empty
532
+ /// types. The changes are:
533
+ /// (0) We don't exit early if the pattern matrix has zero rows. We just
534
+ /// continue to recurse over columns.
535
+ /// (1) all_constructors will only return constructors that are statically
536
+ /// possible. eg. it will only return Ok for Result<T, !>
535
537
///
536
538
/// Whether a vector `v` of patterns is 'useful' in relation to a set of such
537
539
/// vectors `m` is defined as there being a set of inputs that will match `v`
@@ -541,12 +543,9 @@ fn max_slice_length<'a, 'tcx, I>(
541
543
/// relation to preceding patterns, it is not reachable) and exhaustiveness
542
544
/// checking (if a wildcard pattern is useful in relation to a matrix, the
543
545
/// matrix isn't exhaustive).
544
- ///
545
- /// Note: is_useful doesn't work on empty types, as the paper notes.
546
- /// So it assumes that v is non-empty.
547
- pub fn is_useful < ' a , ' tcx > ( cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
548
- matrix : & Matrix < ' a , ' tcx > ,
549
- v : & [ & ' a Pattern < ' tcx > ] ,
546
+ pub fn is_useful < ' p , ' a : ' p , ' tcx : ' a > ( cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
547
+ matrix : & Matrix < ' p , ' tcx > ,
548
+ v : & [ & ' p Pattern < ' tcx > ] ,
550
549
witness : WitnessPreference )
551
550
-> Usefulness < ' tcx > {
552
551
let & Matrix ( ref rows) = matrix;
@@ -616,19 +615,27 @@ pub fn is_useful<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
616
615
}
617
616
}
618
617
619
- fn is_useful_specialized < ' a , ' tcx > (
618
+ fn is_useful_specialized < ' p , ' a : ' p , ' tcx : ' a > (
620
619
cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
621
- & Matrix ( ref m) : & Matrix < ' a , ' tcx > ,
622
- v : & [ & ' a Pattern < ' tcx > ] ,
620
+ & Matrix ( ref m) : & Matrix < ' p , ' tcx > ,
621
+ v : & [ & ' p Pattern < ' tcx > ] ,
623
622
ctor : Constructor ,
624
623
lty : Ty < ' tcx > ,
625
624
witness : WitnessPreference ) -> Usefulness < ' tcx >
626
625
{
627
- let arity = constructor_arity ( cx, & ctor, lty) ;
626
+ let sub_pat_tys = constructor_sub_pattern_tys ( cx, & ctor, lty) ;
627
+ let wild_patterns_owned: Vec < _ > = sub_pat_tys. iter ( ) . map ( |ty| {
628
+ Pattern {
629
+ ty : ty,
630
+ span : DUMMY_SP ,
631
+ kind : box PatternKind :: Wild ,
632
+ }
633
+ } ) . collect ( ) ;
634
+ let wild_patterns: Vec < _ > = wild_patterns_owned. iter ( ) . collect ( ) ;
628
635
let matrix = Matrix ( m. iter ( ) . flat_map ( |r| {
629
- specialize ( cx, & r[ ..] , & ctor, 0 , arity )
636
+ specialize ( cx, & r[ ..] , & ctor, & wild_patterns )
630
637
} ) . collect ( ) ) ;
631
- match specialize ( cx, v, & ctor, 0 , arity ) {
638
+ match specialize ( cx, v, & ctor, & wild_patterns ) {
632
639
Some ( v) => match is_useful ( cx, & matrix, & v[ ..] , witness) {
633
640
UsefulWithWitness ( witnesses) => UsefulWithWitness (
634
641
witnesses. into_iter ( )
@@ -703,6 +710,33 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize
703
710
}
704
711
}
705
712
713
+ /// This computes the types of the sub patterns that a constructor should be
714
+ /// expanded to.
715
+ ///
716
+ /// For instance, a tuple pattern (43u32, 'a') has sub pattern types [u32, char].
717
+ fn constructor_sub_pattern_tys < ' a , ' tcx : ' a > ( cx : & MatchCheckCtxt < ' a , ' tcx > ,
718
+ ctor : & Constructor ,
719
+ ty : Ty < ' tcx > ) -> Vec < Ty < ' tcx > >
720
+ {
721
+ debug ! ( "constructor_sub_pattern_tys({:?}, {:?})" , ctor, ty) ;
722
+ match ty. sty {
723
+ ty:: TyTuple ( ref fs) => fs. into_iter ( ) . map ( |t| * t) . collect ( ) ,
724
+ ty:: TyBox ( ty) => vec ! [ ty] ,
725
+ ty:: TySlice ( ty) | ty:: TyArray ( ty, _) => match * ctor {
726
+ Slice ( length) => repeat ( ty) . take ( length) . collect ( ) ,
727
+ ConstantValue ( _) => vec ! [ ] ,
728
+ _ => bug ! ( "bad slice pattern {:?} {:?}" , ctor, ty)
729
+ } ,
730
+ ty:: TyRef ( _, ref ty_and_mut) => vec ! [ ty_and_mut. ty] ,
731
+ ty:: TyAdt ( adt, substs) => {
732
+ ctor. variant_for_adt ( adt) . fields . iter ( ) . map ( |field| {
733
+ field. ty ( cx. tcx , substs)
734
+ } ) . collect ( )
735
+ }
736
+ _ => vec ! [ ] ,
737
+ }
738
+ }
739
+
706
740
fn slice_pat_covered_by_constructor ( _tcx : TyCtxt , _span : Span ,
707
741
ctor : & Constructor ,
708
742
prefix : & [ Pattern ] ,
@@ -754,19 +788,18 @@ fn range_covered_by_constructor(tcx: TyCtxt, span: Span,
754
788
Ok ( cmp_from != Ordering :: Less && cmp_to != Ordering :: Greater )
755
789
}
756
790
757
- fn patterns_for_variant < ' a , ' tcx > (
758
- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
759
- subpatterns : & ' a [ FieldPattern < ' tcx > ] ,
760
- arity : usize )
761
- -> Vec < & ' a Pattern < ' tcx > >
791
+ fn patterns_for_variant < ' p , ' a : ' p , ' tcx : ' a > (
792
+ subpatterns : & ' p [ FieldPattern < ' tcx > ] ,
793
+ wild_patterns : & [ & ' p Pattern < ' tcx > ] )
794
+ -> Vec < & ' p Pattern < ' tcx > >
762
795
{
763
- let mut result = vec ! [ cx . wild_pattern ; arity ] ;
796
+ let mut result = wild_patterns . to_owned ( ) ;
764
797
765
798
for subpat in subpatterns {
766
799
result[ subpat. field . index ( ) ] = & subpat. pattern ;
767
800
}
768
801
769
- debug ! ( "patterns_for_variant({:?}, {:?}) = {:?}" , subpatterns, arity , result) ;
802
+ debug ! ( "patterns_for_variant({:?}, {:?}) = {:?}" , subpatterns, wild_patterns , result) ;
770
803
result
771
804
}
772
805
@@ -778,35 +811,41 @@ fn patterns_for_variant<'a, 'tcx>(
778
811
/// different patterns.
779
812
/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
780
813
/// fields filled with wild patterns.
781
- fn specialize < ' a , ' tcx > (
814
+ fn specialize < ' p , ' a : ' p , ' tcx : ' a > (
782
815
cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
783
- r : & [ & ' a Pattern < ' tcx > ] ,
784
- constructor : & Constructor , col : usize , arity : usize )
785
- -> Option < Vec < & ' a Pattern < ' tcx > > >
816
+ r : & [ & ' p Pattern < ' tcx > ] ,
817
+ constructor : & Constructor ,
818
+ wild_patterns : & [ & ' p Pattern < ' tcx > ] )
819
+ -> Option < Vec < & ' p Pattern < ' tcx > > >
786
820
{
787
- let pat = & r[ col ] ;
821
+ let pat = & r[ 0 ] ;
788
822
789
823
let head: Option < Vec < & Pattern > > = match * pat. kind {
790
- PatternKind :: Binding { .. } | PatternKind :: Wild =>
791
- Some ( vec ! [ cx. wild_pattern; arity] ) ,
824
+ PatternKind :: Binding { .. } | PatternKind :: Wild => {
825
+ Some ( wild_patterns. to_owned ( ) )
826
+ } ,
792
827
793
- PatternKind :: Variant { adt_def, variant_index, ref subpatterns } => {
828
+ PatternKind :: Variant { adt_def, variant_index, ref subpatterns, .. } => {
794
829
let ref variant = adt_def. variants [ variant_index] ;
795
830
if * constructor == Variant ( variant. did ) {
796
- Some ( patterns_for_variant ( cx , subpatterns, arity ) )
831
+ Some ( patterns_for_variant ( subpatterns, wild_patterns ) )
797
832
} else {
798
833
None
799
834
}
800
835
}
801
836
802
- PatternKind :: Leaf { ref subpatterns } => Some ( patterns_for_variant ( cx, subpatterns, arity) ) ,
803
- PatternKind :: Deref { ref subpattern } => Some ( vec ! [ subpattern] ) ,
837
+ PatternKind :: Leaf { ref subpatterns } => {
838
+ Some ( patterns_for_variant ( subpatterns, wild_patterns) )
839
+ }
840
+ PatternKind :: Deref { ref subpattern } => {
841
+ Some ( vec ! [ subpattern] )
842
+ }
804
843
805
844
PatternKind :: Constant { ref value } => {
806
845
match * constructor {
807
846
Slice ( ..) => match * value {
808
847
ConstVal :: ByteStr ( ref data) => {
809
- if arity == data. len ( ) {
848
+ if wild_patterns . len ( ) == data. len ( ) {
810
849
Some ( cx. lower_byte_str_pattern ( pat) )
811
850
} else {
812
851
None
@@ -842,11 +881,14 @@ fn specialize<'a, 'tcx>(
842
881
match * constructor {
843
882
Slice ( ..) => {
844
883
let pat_len = prefix. len ( ) + suffix. len ( ) ;
845
- if let Some ( slice_count) = arity . checked_sub ( pat_len) {
884
+ if let Some ( slice_count) = wild_patterns . len ( ) . checked_sub ( pat_len) {
846
885
if slice_count == 0 || slice. is_some ( ) {
847
886
Some (
848
887
prefix. iter ( ) . chain (
849
- repeat ( cx. wild_pattern ) . take ( slice_count) . chain (
888
+ wild_patterns. iter ( ) . map ( |p| * p)
889
+ . skip ( prefix. len ( ) )
890
+ . take ( slice_count)
891
+ . chain (
850
892
suffix. iter ( )
851
893
) ) . collect ( ) )
852
894
} else {
@@ -870,11 +912,10 @@ fn specialize<'a, 'tcx>(
870
912
}
871
913
}
872
914
} ;
873
- debug ! ( "specialize({:?}, {:?}) = {:?}" , r[ col ] , arity , head) ;
915
+ debug ! ( "specialize({:?}, {:?}) = {:?}" , r[ 0 ] , wild_patterns , head) ;
874
916
875
917
head. map ( |mut head| {
876
- head. extend_from_slice ( & r[ ..col] ) ;
877
- head. extend_from_slice ( & r[ col + 1 ..] ) ;
918
+ head. extend_from_slice ( & r[ 1 ..] ) ;
878
919
head
879
920
} )
880
921
}
0 commit comments