@@ -327,9 +327,23 @@ struct LiteralExpander;
327
327
impl < ' tcx > PatternFolder < ' tcx > for LiteralExpander {
328
328
fn fold_pattern ( & mut self , pat : & Pat < ' tcx > ) -> Pat < ' tcx > {
329
329
debug ! ( "fold_pattern {:?} {:?} {:?}" , pat, pat. ty. kind( ) , pat. kind) ;
330
- match ( pat. ty . kind ( ) , & * pat. kind ) {
331
- ( _, & PatKind :: Binding { subpattern : Some ( ref s) , .. } ) => s. fold_with ( self ) ,
332
- ( _, & PatKind :: AscribeUserType { subpattern : ref s, .. } ) => s. fold_with ( self ) ,
330
+ match ( pat. ty . kind ( ) , pat. kind . as_ref ( ) ) {
331
+ ( _, PatKind :: Binding { subpattern : Some ( s) , .. } ) => s. fold_with ( self ) ,
332
+ ( _, PatKind :: AscribeUserType { subpattern : s, .. } ) => s. fold_with ( self ) ,
333
+ ( ty:: Ref ( _, t, _) , PatKind :: Constant { .. } ) if t. is_str ( ) => {
334
+ // Treat string literal patterns as deref patterns to a `str` constant, i.e.
335
+ // `&CONST`. This expands them like other const patterns. This could have been done
336
+ // in `const_to_pat`, but that causes issues with the rest of the matching code.
337
+ let mut new_pat = pat. super_fold_with ( self ) ;
338
+ // Make a fake const pattern of type `str` (instead of `&str`). That the carried
339
+ // constant value still knows it is of type `&str`.
340
+ new_pat. ty = t;
341
+ Pat {
342
+ kind : Box :: new ( PatKind :: Deref { subpattern : new_pat } ) ,
343
+ span : pat. span ,
344
+ ty : pat. ty ,
345
+ }
346
+ }
333
347
_ => pat. super_fold_with ( self ) ,
334
348
}
335
349
}
@@ -782,11 +796,9 @@ enum Constructor<'tcx> {
782
796
/// boxes for the purposes of exhaustiveness: we must not inspect them, and they
783
797
/// don't count towards making a match exhaustive.
784
798
Opaque ,
785
- /// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
799
+ /// Fake extra constructor for enums that aren't allowed to be matched exhaustively. Also used
800
+ /// for those types for which we cannot list constructors explicitly, like `f64` and `str`.
786
801
NonExhaustive ,
787
- /// Fake constructor for those types for which we can't list constructors explicitly, like
788
- /// `f64` and `&str`.
789
- Unlistable ,
790
802
/// Wildcard pattern.
791
803
Wildcard ,
792
804
}
@@ -880,6 +892,7 @@ impl<'tcx> Constructor<'tcx> {
880
892
/// For the simple cases, this is simply checking for equality. For the "grouped" constructors,
881
893
/// this checks for inclusion.
882
894
fn is_covered_by < ' p > ( & self , pcx : PatCtxt < ' _ , ' p , ' tcx > , other : & Self ) -> bool {
895
+ // This must be kept in sync with `is_covered_by_any`.
883
896
match ( self , other) {
884
897
// Wildcards cover anything
885
898
( _, Wildcard ) => true ,
@@ -922,18 +935,19 @@ impl<'tcx> Constructor<'tcx> {
922
935
( Opaque , _) | ( _, Opaque ) => false ,
923
936
// Only a wildcard pattern can match the special extra constructor.
924
937
( NonExhaustive , _) => false ,
925
- // If we encounter a `Single` here, this means there was only one constructor for this
926
- // type after all.
927
- ( Unlistable , Single ) => true ,
928
- // Otherwise, only a wildcard pattern can match the special extra constructor.
929
- ( Unlistable , _) => false ,
930
938
931
- _ => bug ! ( "trying to compare incompatible constructors {:?} and {:?}" , self , other) ,
939
+ _ => span_bug ! (
940
+ pcx. span,
941
+ "trying to compare incompatible constructors {:?} and {:?}" ,
942
+ self ,
943
+ other
944
+ ) ,
932
945
}
933
946
}
934
947
935
948
/// Faster version of `is_covered_by` when applied to many constructors. `used_ctors` is
936
- /// assumed to be built from `matrix.head_ctors()`, and `self` is assumed to have been split.
949
+ /// assumed to be built from `matrix.head_ctors()` with wildcards filtered out, and `self` is
950
+ /// assumed to have been split from a wildcard.
937
951
fn is_covered_by_any < ' p > (
938
952
& self ,
939
953
pcx : PatCtxt < ' _ , ' p , ' tcx > ,
@@ -943,8 +957,9 @@ impl<'tcx> Constructor<'tcx> {
943
957
return false ;
944
958
}
945
959
960
+ // This must be kept in sync with `is_covered_by`.
946
961
match self {
947
- // `used_ctors` cannot contain anything else than `Single`s.
962
+ // If `self` is `Single`, `used_ctors` cannot contain anything else than `Single`s.
948
963
Single => !used_ctors. is_empty ( ) ,
949
964
Variant ( _) => used_ctors. iter ( ) . any ( |c| c == self ) ,
950
965
IntRange ( range) => used_ctors
@@ -957,8 +972,6 @@ impl<'tcx> Constructor<'tcx> {
957
972
. any ( |other| slice. is_covered_by ( other) ) ,
958
973
// This constructor is never covered by anything else
959
974
NonExhaustive => false ,
960
- // This constructor is only covered by `Single`s
961
- Unlistable => used_ctors. iter ( ) . any ( |c| * c == Single ) ,
962
975
Str ( ..) | FloatRange ( ..) | Opaque | Wildcard => {
963
976
bug ! ( "found unexpected ctor in all_ctors: {:?}" , self )
964
977
}
@@ -1006,6 +1019,10 @@ impl<'tcx> Constructor<'tcx> {
1006
1019
PatKind :: Leaf { subpatterns }
1007
1020
}
1008
1021
}
1022
+ // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
1023
+ // be careful to reconstruct the correct constant pattern here. However a string
1024
+ // literal pattern will never be reported as a non-exhaustiveness witness, so we
1025
+ // can ignore this issue.
1009
1026
ty:: Ref ( ..) => PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) } ,
1010
1027
ty:: Slice ( _) | ty:: Array ( ..) => bug ! ( "bad slice pattern {:?} {:?}" , self , pcx. ty) ,
1011
1028
_ => PatKind :: Wild ,
@@ -1038,7 +1055,7 @@ impl<'tcx> Constructor<'tcx> {
1038
1055
& Str ( value) => PatKind :: Constant { value } ,
1039
1056
& FloatRange ( lo, hi, end) => PatKind :: Range ( PatRange { lo, hi, end } ) ,
1040
1057
IntRange ( range) => return range. to_pat ( pcx. cx . tcx ) ,
1041
- NonExhaustive | Unlistable => PatKind :: Wild ,
1058
+ NonExhaustive => PatKind :: Wild ,
1042
1059
Opaque => bug ! ( "we should not try to apply an opaque constructor" ) ,
1043
1060
Wildcard => bug ! (
1044
1061
"trying to apply a wildcard constructor; this should have been done in `apply_constructors`"
@@ -1187,8 +1204,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1187
1204
}
1188
1205
_ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, ty) ,
1189
1206
} ,
1190
- Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque | Unlistable
1191
- | Wildcard => Fields :: empty ( ) ,
1207
+ Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque | Wildcard => {
1208
+ Fields :: empty ( )
1209
+ }
1192
1210
} ;
1193
1211
debug ! ( "Fields::wildcards({:?}, {:?}) = {:#?}" , constructor, ty, ret) ;
1194
1212
ret
@@ -1300,9 +1318,13 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1300
1318
/// [Some(0), ..] => {}
1301
1319
/// }
1302
1320
/// ```
1321
+ /// This is guaranteed to preserve the number of patterns in `self`.
1303
1322
fn replace_with_pattern_arguments ( & self , pat : & ' p Pat < ' tcx > ) -> Self {
1304
1323
match pat. kind . as_ref ( ) {
1305
- PatKind :: Deref { subpattern } => Self :: from_single_pattern ( subpattern) ,
1324
+ PatKind :: Deref { subpattern } => {
1325
+ assert_eq ! ( self . len( ) , 1 ) ;
1326
+ Fields :: from_single_pattern ( subpattern)
1327
+ }
1306
1328
PatKind :: Leaf { subpatterns } | PatKind :: Variant { subpatterns, .. } => {
1307
1329
self . replace_with_fieldpats ( subpatterns)
1308
1330
}
@@ -1590,10 +1612,9 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
1590
1612
vec ! [ make_range( 0 , max) ]
1591
1613
}
1592
1614
_ if cx. is_uninhabited ( pcx. ty ) => vec ! [ ] ,
1593
- ty:: Adt ( ..) | ty:: Tuple ( ..) => vec ! [ Single ] ,
1594
- ty:: Ref ( _, t, _) if !t. is_str ( ) => vec ! [ Single ] ,
1595
- // This type is one for which we don't know how to list constructors, like `&str` or `f64`.
1596
- _ => vec ! [ Unlistable ] ,
1615
+ ty:: Adt ( ..) | ty:: Tuple ( ..) | ty:: Ref ( ..) => vec ! [ Single ] ,
1616
+ // This type is one for which we cannot list constructors, like `str` or `f64`.
1617
+ _ => vec ! [ NonExhaustive ] ,
1597
1618
}
1598
1619
}
1599
1620
@@ -2152,28 +2173,31 @@ fn pat_constructor<'p, 'tcx>(
2152
2173
cx : & MatchCheckCtxt < ' p , ' tcx > ,
2153
2174
pat : & ' p Pat < ' tcx > ,
2154
2175
) -> Constructor < ' tcx > {
2155
- match * pat. kind {
2176
+ match pat. kind . as_ref ( ) {
2156
2177
PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled by `expand_pattern`
2157
2178
PatKind :: Binding { .. } | PatKind :: Wild => Wildcard ,
2158
2179
PatKind :: Leaf { .. } | PatKind :: Deref { .. } => Single ,
2159
- PatKind :: Variant { adt_def, variant_index, .. } => {
2180
+ & PatKind :: Variant { adt_def, variant_index, .. } => {
2160
2181
Variant ( adt_def. variants [ variant_index] . def_id )
2161
2182
}
2162
2183
PatKind :: Constant { value } => {
2163
2184
if let Some ( int_range) = IntRange :: from_const ( cx. tcx , cx. param_env , value, pat. span ) {
2164
2185
IntRange ( int_range)
2165
2186
} else {
2166
- match value . ty . kind ( ) {
2187
+ match pat . ty . kind ( ) {
2167
2188
ty:: Float ( _) => FloatRange ( value, value, RangeEnd :: Included ) ,
2168
- ty:: Ref ( _, t, _) if t. is_str ( ) => Str ( value) ,
2189
+ // In `expand_pattern`, we convert string literals to `&CONST` patterns with
2190
+ // `CONST` a pattern of type `str`. In truth this contains a constant of type
2191
+ // `&str`.
2192
+ ty:: Str => Str ( value) ,
2169
2193
// All constants that can be structurally matched have already been expanded
2170
2194
// into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
2171
2195
// opaque.
2172
2196
_ => Opaque ,
2173
2197
}
2174
2198
}
2175
2199
}
2176
- PatKind :: Range ( PatRange { lo, hi, end } ) => {
2200
+ & PatKind :: Range ( PatRange { lo, hi, end } ) => {
2177
2201
let ty = lo. ty ;
2178
2202
if let Some ( int_range) = IntRange :: from_range (
2179
2203
cx. tcx ,
@@ -2188,8 +2212,7 @@ fn pat_constructor<'p, 'tcx>(
2188
2212
FloatRange ( lo, hi, end)
2189
2213
}
2190
2214
}
2191
- PatKind :: Array { ref prefix, ref slice, ref suffix }
2192
- | PatKind :: Slice { ref prefix, ref slice, ref suffix } => {
2215
+ PatKind :: Array { prefix, slice, suffix } | PatKind :: Slice { prefix, slice, suffix } => {
2193
2216
let array_len = match pat. ty . kind ( ) {
2194
2217
ty:: Array ( _, length) => Some ( length. eval_usize ( cx. tcx , cx. param_env ) ) ,
2195
2218
ty:: Slice ( _) => None ,
0 commit comments