@@ -52,7 +52,55 @@ pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
52
52
span : DUMMY_SP
53
53
} ;
54
54
55
- struct Matrix < ' a , ' tcx > ( Vec < Vec < ( & ' a Pat , Option < Ty < ' tcx > > ) > > ) ;
55
+ pub const DUMMY_WILD_PATTERN : Pattern < ' static , ' static > = Pattern {
56
+ pat : DUMMY_WILD_PAT ,
57
+ pattern_ty : None
58
+ } ;
59
+
60
+ #[ derive( Copy , Clone ) ]
61
+ pub struct Pattern < ' a , ' tcx > {
62
+ pat : & ' a Pat ,
63
+ pattern_ty : Option < Ty < ' tcx > >
64
+ }
65
+
66
+ impl < ' a , ' tcx > Pattern < ' a , ' tcx > {
67
+ fn as_raw ( self ) -> & ' a Pat {
68
+ let mut pat = self . pat ;
69
+
70
+ while let PatKind :: Binding ( .., Some ( ref s) ) = pat. node {
71
+ pat = s;
72
+ }
73
+
74
+ return pat;
75
+ }
76
+
77
+
78
+ /// Checks for common cases of "catchall" patterns that may not be intended as such.
79
+ fn is_catchall ( self , dm : & DefMap ) -> bool {
80
+ fn is_catchall ( dm : & DefMap , pat : & Pat ) -> bool {
81
+ match pat. node {
82
+ PatKind :: Binding ( .., None ) => true ,
83
+ PatKind :: Binding ( .., Some ( ref s) ) => is_catchall ( dm, s) ,
84
+ PatKind :: Ref ( ref s, _) => is_catchall ( dm, s) ,
85
+ PatKind :: Tuple ( ref v, _) => v. iter ( ) . all ( |p|is_catchall ( dm, & p) ) ,
86
+ _ => false
87
+ }
88
+ }
89
+ is_catchall ( dm, self . pat )
90
+ }
91
+
92
+ fn span ( self ) -> Span {
93
+ self . pat . span
94
+ }
95
+ }
96
+
97
+ struct Matrix < ' a , ' tcx > ( Vec < Vec < Pattern < ' a , ' tcx > > > ) ;
98
+
99
+ impl < ' a , ' tcx > fmt:: Debug for Pattern < ' a , ' tcx > {
100
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
101
+ write ! ( f, "{}: {:?}" , pat_to_string( self . pat) , self . pattern_ty)
102
+ }
103
+ }
56
104
57
105
/// Pretty-printer for matrices of patterns, example:
58
106
/// ++++++++++++++++++++++++++
@@ -72,9 +120,7 @@ impl<'a, 'tcx> fmt::Debug for Matrix<'a, 'tcx> {
72
120
73
121
let & Matrix ( ref m) = self ;
74
122
let pretty_printed_matrix: Vec < Vec < String > > = m. iter ( ) . map ( |row| {
75
- row. iter ( )
76
- . map ( |& ( pat, ty) | format ! ( "{}: {:?}" , pat_to_string( & pat) , ty) )
77
- . collect :: < Vec < String > > ( )
123
+ row. iter ( ) . map ( |pat| format ! ( "{:?}" , pat) ) . collect ( )
78
124
} ) . collect ( ) ;
79
125
80
126
let column_count = m. iter ( ) . map ( |row| row. len ( ) ) . max ( ) . unwrap_or ( 0 ) ;
@@ -100,9 +146,8 @@ impl<'a, 'tcx> fmt::Debug for Matrix<'a, 'tcx> {
100
146
}
101
147
}
102
148
103
- impl < ' a , ' tcx > FromIterator < Vec < ( & ' a Pat , Option < Ty < ' tcx > > ) > > for Matrix < ' a , ' tcx > {
104
- fn from_iter < T : IntoIterator < Item =Vec < ( & ' a Pat , Option < Ty < ' tcx > > ) > > > ( iter : T )
105
- -> Self
149
+ impl < ' a , ' tcx > FromIterator < Vec < Pattern < ' a , ' tcx > > > for Matrix < ' a , ' tcx > {
150
+ fn from_iter < T : IntoIterator < Item =Vec < Pattern < ' a , ' tcx > > > > ( iter : T ) -> Self
106
151
{
107
152
Matrix ( iter. into_iter ( ) . collect ( ) )
108
153
}
@@ -349,8 +394,8 @@ fn check_arms(cx: &MatchCheckCtxt,
349
394
err. span_label ( pat. span , & format ! ( "this is an unreachable pattern" ) ) ;
350
395
// if we had a catchall pattern, hint at that
351
396
for row in & seen. 0 {
352
- if pat_is_catchall ( & cx. tcx . def_map . borrow ( ) , row [ 0 ] . 0 ) {
353
- span_note ! ( err, row[ 0 ] . 0 . span,
397
+ if row [ 0 ] . is_catchall ( & cx. tcx . def_map . borrow ( ) ) {
398
+ span_note ! ( err, row[ 0 ] . span( ) ,
354
399
"this pattern matches any value" ) ;
355
400
}
356
401
}
@@ -374,29 +419,11 @@ fn check_arms(cx: &MatchCheckCtxt,
374
419
}
375
420
}
376
421
377
- /// Checks for common cases of "catchall" patterns that may not be intended as such.
378
- fn pat_is_catchall ( dm : & DefMap , p : & Pat ) -> bool {
379
- match p. node {
380
- PatKind :: Binding ( .., None ) => true ,
381
- PatKind :: Binding ( .., Some ( ref s) ) => pat_is_catchall ( dm, & s) ,
382
- PatKind :: Ref ( ref s, _) => pat_is_catchall ( dm, & s) ,
383
- PatKind :: Tuple ( ref v, _) => v. iter ( ) . all ( |p| pat_is_catchall ( dm, & p) ) ,
384
- _ => false
385
- }
386
- }
387
-
388
- fn raw_pat ( p : & Pat ) -> & Pat {
389
- match p. node {
390
- PatKind :: Binding ( .., Some ( ref s) ) => raw_pat ( & s) ,
391
- _ => p
392
- }
393
- }
394
-
395
422
fn check_exhaustive < ' a , ' tcx > ( cx : & MatchCheckCtxt < ' a , ' tcx > ,
396
423
sp : Span ,
397
424
matrix : & Matrix < ' a , ' tcx > ,
398
425
source : hir:: MatchSource ) {
399
- match is_useful ( cx, matrix, & [ ( DUMMY_WILD_PAT , None ) ] , ConstructWitness ) {
426
+ match is_useful ( cx, matrix, & [ DUMMY_WILD_PATTERN ] , ConstructWitness ) {
400
427
UsefulWithWitness ( pats) => {
401
428
let witnesses = if pats. is_empty ( ) {
402
429
vec ! [ DUMMY_WILD_PAT ]
@@ -655,7 +682,7 @@ impl Constructor {
655
682
fn missing_constructors ( cx : & MatchCheckCtxt , & Matrix ( ref rows) : & Matrix ,
656
683
left_ty : Ty , max_slice_length : usize ) -> Vec < Constructor > {
657
684
let used_constructors: Vec < Constructor > = rows. iter ( )
658
- . flat_map ( |row| pat_constructors ( cx, row[ 0 ] . 0 , left_ty, max_slice_length) )
685
+ . flat_map ( |row| pat_constructors ( cx, row[ 0 ] , left_ty, max_slice_length) )
659
686
. collect ( ) ;
660
687
all_constructors ( cx, left_ty, max_slice_length)
661
688
. into_iter ( )
@@ -695,7 +722,7 @@ fn all_constructors(_cx: &MatchCheckCtxt, left_ty: Ty,
695
722
// So it assumes that v is non-empty.
696
723
fn is_useful < ' a , ' tcx > ( cx : & MatchCheckCtxt < ' a , ' tcx > ,
697
724
matrix : & Matrix < ' a , ' tcx > ,
698
- v : & [ ( & Pat , Option < Ty < ' tcx > > ) ] ,
725
+ v : & [ Pattern < ' a , ' tcx > ] ,
699
726
witness : WitnessPreference )
700
727
-> Usefulness {
701
728
let & Matrix ( ref rows) = matrix;
@@ -710,20 +737,22 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
710
737
return NotUseful ;
711
738
}
712
739
assert ! ( rows. iter( ) . all( |r| r. len( ) == v. len( ) ) ) ;
713
- let left_ty = match rows. iter ( ) . filter_map ( |r| r[ 0 ] . 1 ) . next ( ) . or_else ( || v[ 0 ] . 1 ) {
740
+ let left_ty = match rows. iter ( ) . filter_map ( |r| r[ 0 ] . pattern_ty ) . next ( )
741
+ . or_else ( || v[ 0 ] . pattern_ty )
742
+ {
714
743
Some ( ty) => ty,
715
744
None => {
716
745
// all patterns are wildcards - we can pick any type we want
717
746
cx. tcx . types . bool
718
747
}
719
748
} ;
720
749
721
- let max_slice_length = rows. iter ( ) . filter_map ( |row| match row[ 0 ] . 0 . node {
750
+ let max_slice_length = rows. iter ( ) . filter_map ( |row| match row[ 0 ] . pat . node {
722
751
PatKind :: Slice ( ref before, _, ref after) => Some ( before. len ( ) + after. len ( ) ) ,
723
752
_ => None
724
753
} ) . max ( ) . map_or ( 0 , |v| v + 1 ) ;
725
754
726
- let constructors = pat_constructors ( cx, v[ 0 ] . 0 , left_ty, max_slice_length) ;
755
+ let constructors = pat_constructors ( cx, v[ 0 ] , left_ty, max_slice_length) ;
727
756
debug ! ( "is_useful - pat_constructors = {:?} left_ty = {:?}" , constructors,
728
757
left_ty) ;
729
758
if constructors. is_empty ( ) {
@@ -749,7 +778,7 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
749
778
} ) . find ( |result| result != & NotUseful ) . unwrap_or ( NotUseful )
750
779
} else {
751
780
let matrix = rows. iter ( ) . filter_map ( |r| {
752
- match raw_pat ( r[ 0 ] . 0 ) . node {
781
+ match r[ 0 ] . as_raw ( ) . node {
753
782
PatKind :: Binding ( ..) | PatKind :: Wild => Some ( r[ 1 ..] . to_vec ( ) ) ,
754
783
_ => None ,
755
784
}
@@ -777,7 +806,7 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
777
806
fn is_useful_specialized < ' a , ' tcx > (
778
807
cx : & MatchCheckCtxt < ' a , ' tcx > ,
779
808
& Matrix ( ref m) : & Matrix < ' a , ' tcx > ,
780
- v : & [ ( & Pat , Option < Ty < ' tcx > > ) ] ,
809
+ v : & [ Pattern < ' a , ' tcx > ] ,
781
810
ctor : Constructor ,
782
811
lty : Ty < ' tcx > ,
783
812
witness : WitnessPreference ) -> Usefulness
@@ -801,18 +830,18 @@ fn is_useful_specialized<'a, 'tcx>(
801
830
///
802
831
/// On the other hand, a wild pattern and an identifier pattern cannot be
803
832
/// specialized in any way.
804
- fn pat_constructors ( cx : & MatchCheckCtxt , p : & Pat ,
833
+ fn pat_constructors ( cx : & MatchCheckCtxt , p : Pattern ,
805
834
left_ty : Ty , max_slice_length : usize ) -> Vec < Constructor > {
806
- let pat = raw_pat ( p ) ;
835
+ let pat = p . as_raw ( ) ;
807
836
match pat. node {
808
837
PatKind :: Struct ( ..) | PatKind :: TupleStruct ( ..) | PatKind :: Path ( ..) =>
809
838
match cx. tcx . expect_def ( pat. id ) {
810
839
Def :: Variant ( id) | Def :: VariantCtor ( id, ..) => vec ! [ Variant ( id) ] ,
811
840
Def :: Struct ( ..) | Def :: StructCtor ( ..) | Def :: Union ( ..) |
812
841
Def :: TyAlias ( ..) | Def :: AssociatedTy ( ..) => vec ! [ Single ] ,
813
842
Def :: Const ( ..) | Def :: AssociatedConst ( ..) =>
814
- span_bug ! ( pat . span, "const pattern should've been rewritten" ) ,
815
- def => span_bug ! ( pat . span, "pat_constructors: unexpected definition {:?}" , def) ,
843
+ span_bug ! ( p . span( ) , "const pattern should've been rewritten" ) ,
844
+ def => span_bug ! ( p . span( ) , "pat_constructors: unexpected definition {:?}" , def) ,
816
845
} ,
817
846
PatKind :: Lit ( ref expr) =>
818
847
vec ! [ ConstantValue ( eval_const_expr( cx. tcx, & expr) ) ] ,
@@ -881,15 +910,18 @@ fn range_covered_by_constructor(tcx: TyCtxt, span: Span,
881
910
882
911
fn wrap_pat < ' a , ' b , ' tcx > ( cx : & MatchCheckCtxt < ' b , ' tcx > ,
883
912
pat : & ' a Pat )
884
- -> ( & ' a Pat , Option < Ty < ' tcx > > )
913
+ -> Pattern < ' a , ' tcx >
885
914
{
886
915
let pat_ty = cx. tcx . pat_ty ( pat) ;
887
- ( pat, Some ( match pat. node {
888
- PatKind :: Binding ( hir:: BindByRef ( ..) , ..) => {
889
- pat_ty. builtin_deref ( false , ty:: NoPreference ) . unwrap ( ) . ty
890
- }
891
- _ => pat_ty
892
- } ) )
916
+ Pattern {
917
+ pat : pat,
918
+ pattern_ty : Some ( match pat. node {
919
+ PatKind :: Binding ( hir:: BindByRef ( ..) , ..) => {
920
+ pat_ty. builtin_deref ( false , ty:: NoPreference ) . unwrap ( ) . ty
921
+ }
922
+ _ => pat_ty
923
+ } )
924
+ }
893
925
}
894
926
895
927
/// This is the main specialization step. It expands the first pattern in the given row
@@ -902,20 +934,19 @@ fn wrap_pat<'a, 'b, 'tcx>(cx: &MatchCheckCtxt<'b, 'tcx>,
902
934
/// fields filled with wild patterns.
903
935
pub fn specialize < ' a , ' b , ' tcx > (
904
936
cx : & MatchCheckCtxt < ' b , ' tcx > ,
905
- r : & [ ( & ' a Pat , Option < Ty < ' tcx > > ) ] ,
937
+ r : & [ Pattern < ' a , ' tcx > ] ,
906
938
constructor : & Constructor , col : usize , arity : usize )
907
- -> Option < Vec < ( & ' a Pat , Option < Ty < ' tcx > > ) > >
939
+ -> Option < Vec < Pattern < ' a , ' tcx > > >
908
940
{
909
- let pat = raw_pat ( r[ col] . 0 ) ;
941
+ let pat = r[ col] . as_raw ( ) ;
910
942
let & Pat {
911
943
id : pat_id, ref node, span : pat_span
912
944
} = pat;
913
945
let wpat = |pat : & ' a Pat | wrap_pat ( cx, pat) ;
914
- let dummy_pat = ( DUMMY_WILD_PAT , None ) ;
915
946
916
- let head: Option < Vec < ( & Pat , Option < Ty > ) > > = match * node {
947
+ let head: Option < Vec < Pattern > > = match * node {
917
948
PatKind :: Binding ( ..) | PatKind :: Wild =>
918
- Some ( vec ! [ dummy_pat ; arity] ) ,
949
+ Some ( vec ! [ DUMMY_WILD_PATTERN ; arity] ) ,
919
950
920
951
PatKind :: Path ( ..) => {
921
952
match cx. tcx . expect_def ( pat_id) {
@@ -942,7 +973,7 @@ pub fn specialize<'a, 'b, 'tcx>(
942
973
let mut pats: Vec < _ > = args[ ..ddpos] . iter ( ) . map ( |p| {
943
974
wpat ( p)
944
975
} ) . collect ( ) ;
945
- pats. extend ( repeat ( ( DUMMY_WILD_PAT , None ) ) . take ( arity - args. len ( ) ) ) ;
976
+ pats. extend ( repeat ( DUMMY_WILD_PATTERN ) . take ( arity - args. len ( ) ) ) ;
946
977
pats. extend ( args[ ddpos..] . iter ( ) . map ( |p| wpat ( p) ) ) ;
947
978
Some ( pats)
948
979
}
@@ -961,7 +992,7 @@ pub fn specialize<'a, 'b, 'tcx>(
961
992
Some ( variant. fields . iter ( ) . map ( |sf| {
962
993
match pattern_fields. iter ( ) . find ( |f| f. node . name == sf. name ) {
963
994
Some ( ref f) => wpat ( & f. node . pat ) ,
964
- _ => dummy_pat
995
+ _ => DUMMY_WILD_PATTERN
965
996
}
966
997
} ) . collect ( ) )
967
998
} else {
@@ -971,7 +1002,7 @@ pub fn specialize<'a, 'b, 'tcx>(
971
1002
972
1003
PatKind :: Tuple ( ref args, Some ( ddpos) ) => {
973
1004
let mut pats: Vec < _ > = args[ ..ddpos] . iter ( ) . map ( |p| wpat ( p) ) . collect ( ) ;
974
- pats. extend ( repeat ( dummy_pat ) . take ( arity - args. len ( ) ) ) ;
1005
+ pats. extend ( repeat ( DUMMY_WILD_PATTERN ) . take ( arity - args. len ( ) ) ) ;
975
1006
pats. extend ( args[ ddpos..] . iter ( ) . map ( |p| wpat ( p) ) ) ;
976
1007
Some ( pats)
977
1008
}
@@ -982,12 +1013,15 @@ pub fn specialize<'a, 'b, 'tcx>(
982
1013
Some ( vec ! [ wpat( & * * inner) ] ) ,
983
1014
984
1015
PatKind :: Lit ( ref expr) => {
985
- match r[ col] . 1 {
1016
+ match r[ col] . pattern_ty {
986
1017
Some ( & ty:: TyS { sty : ty:: TyRef ( _, mt) , .. } ) => {
987
1018
// HACK: handle string literals. A string literal pattern
988
1019
// serves both as an unary reference pattern and as a
989
1020
// nullary value pattern, depending on the type.
990
- Some ( vec ! [ ( pat, Some ( mt. ty) ) ] )
1021
+ Some ( vec ! [ Pattern {
1022
+ pat: pat,
1023
+ pattern_ty: Some ( mt. ty)
1024
+ } ] )
991
1025
}
992
1026
Some ( ty) => {
993
1027
assert_eq ! ( constructor_arity( cx, constructor, ty) , 0 ) ;
@@ -1023,14 +1057,14 @@ pub fn specialize<'a, 'b, 'tcx>(
1023
1057
// Fixed-length vectors.
1024
1058
Some (
1025
1059
before. iter ( ) . map ( |p| wpat ( p) ) . chain (
1026
- repeat ( dummy_pat ) . take ( arity - pat_len) . chain (
1060
+ repeat ( DUMMY_WILD_PATTERN ) . take ( arity - pat_len) . chain (
1027
1061
after. iter ( ) . map ( |p| wpat ( p) )
1028
1062
) ) . collect ( ) )
1029
1063
} ,
1030
1064
Slice ( length) if pat_len <= length && slice. is_some ( ) => {
1031
1065
Some (
1032
1066
before. iter ( ) . map ( |p| wpat ( p) ) . chain (
1033
- repeat ( dummy_pat ) . take ( arity - pat_len) . chain (
1067
+ repeat ( DUMMY_WILD_PATTERN ) . take ( arity - pat_len) . chain (
1034
1068
after. iter ( ) . map ( |p| wpat ( p) )
1035
1069
) ) . collect ( ) )
1036
1070
}
@@ -1105,7 +1139,7 @@ fn is_refutable<A, F>(cx: &MatchCheckCtxt, pat: &Pat, refutable: F) -> Option<A>
1105
1139
F : FnOnce ( & Pat ) -> A ,
1106
1140
{
1107
1141
let pats = Matrix ( vec ! ( vec!( wrap_pat( cx, pat) ) ) ) ;
1108
- match is_useful ( cx, & pats, & [ ( DUMMY_WILD_PAT , None ) ] , ConstructWitness ) {
1142
+ match is_useful ( cx, & pats, & [ DUMMY_WILD_PATTERN ] , ConstructWitness ) {
1109
1143
UsefulWithWitness ( pats) => Some ( refutable ( & pats[ 0 ] ) ) ,
1110
1144
NotUseful => None ,
1111
1145
Useful => bug ! ( )
0 commit comments