@@ -327,9 +327,23 @@ struct LiteralExpander;
327327impl < ' tcx > PatternFolder < ' tcx > for LiteralExpander {
328328 fn fold_pattern ( & mut self , pat : & Pat < ' tcx > ) -> Pat < ' tcx > {
329329 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+ }
333347 _ => pat. super_fold_with ( self ) ,
334348 }
335349 }
@@ -782,11 +796,9 @@ enum Constructor<'tcx> {
782796 /// boxes for the purposes of exhaustiveness: we must not inspect them, and they
783797 /// don't count towards making a match exhaustive.
784798 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`.
786801 NonExhaustive ,
787- /// Fake constructor for those types for which we can't list constructors explicitly, like
788- /// `f64` and `&str`.
789- Unlistable ,
790802 /// Wildcard pattern.
791803 Wildcard ,
792804}
@@ -880,6 +892,7 @@ impl<'tcx> Constructor<'tcx> {
880892 /// For the simple cases, this is simply checking for equality. For the "grouped" constructors,
881893 /// this checks for inclusion.
882894 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`.
883896 match ( self , other) {
884897 // Wildcards cover anything
885898 ( _, Wildcard ) => true ,
@@ -922,18 +935,19 @@ impl<'tcx> Constructor<'tcx> {
922935 ( Opaque , _) | ( _, Opaque ) => false ,
923936 // Only a wildcard pattern can match the special extra constructor.
924937 ( 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 ,
930938
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+ ) ,
932945 }
933946 }
934947
935948 /// 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.
937951 fn is_covered_by_any < ' p > (
938952 & self ,
939953 pcx : PatCtxt < ' _ , ' p , ' tcx > ,
@@ -943,8 +957,9 @@ impl<'tcx> Constructor<'tcx> {
943957 return false ;
944958 }
945959
960+ // This must be kept in sync with `is_covered_by`.
946961 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.
948963 Single => !used_ctors. is_empty ( ) ,
949964 Variant ( _) => used_ctors. iter ( ) . any ( |c| c == self ) ,
950965 IntRange ( range) => used_ctors
@@ -957,8 +972,6 @@ impl<'tcx> Constructor<'tcx> {
957972 . any ( |other| slice. is_covered_by ( other) ) ,
958973 // This constructor is never covered by anything else
959974 NonExhaustive => false ,
960- // This constructor is only covered by `Single`s
961- Unlistable => used_ctors. iter ( ) . any ( |c| * c == Single ) ,
962975 Str ( ..) | FloatRange ( ..) | Opaque | Wildcard => {
963976 bug ! ( "found unexpected ctor in all_ctors: {:?}" , self )
964977 }
@@ -1006,6 +1019,10 @@ impl<'tcx> Constructor<'tcx> {
10061019 PatKind :: Leaf { subpatterns }
10071020 }
10081021 }
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.
10091026 ty:: Ref ( ..) => PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) } ,
10101027 ty:: Slice ( _) | ty:: Array ( ..) => bug ! ( "bad slice pattern {:?} {:?}" , self , pcx. ty) ,
10111028 _ => PatKind :: Wild ,
@@ -1038,7 +1055,7 @@ impl<'tcx> Constructor<'tcx> {
10381055 & Str ( value) => PatKind :: Constant { value } ,
10391056 & FloatRange ( lo, hi, end) => PatKind :: Range ( PatRange { lo, hi, end } ) ,
10401057 IntRange ( range) => return range. to_pat ( pcx. cx . tcx ) ,
1041- NonExhaustive | Unlistable => PatKind :: Wild ,
1058+ NonExhaustive => PatKind :: Wild ,
10421059 Opaque => bug ! ( "we should not try to apply an opaque constructor" ) ,
10431060 Wildcard => bug ! (
10441061 "trying to apply a wildcard constructor; this should have been done in `apply_constructors`"
@@ -1187,8 +1204,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11871204 }
11881205 _ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, ty) ,
11891206 } ,
1190- Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque | Unlistable
1191- | Wildcard => Fields :: empty ( ) ,
1207+ Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque | Wildcard => {
1208+ Fields :: empty ( )
1209+ }
11921210 } ;
11931211 debug ! ( "Fields::wildcards({:?}, {:?}) = {:#?}" , constructor, ty, ret) ;
11941212 ret
@@ -1300,9 +1318,13 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
13001318 /// [Some(0), ..] => {}
13011319 /// }
13021320 /// ```
1321+ /// This is guaranteed to preserve the number of patterns in `self`.
13031322 fn replace_with_pattern_arguments ( & self , pat : & ' p Pat < ' tcx > ) -> Self {
13041323 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+ }
13061328 PatKind :: Leaf { subpatterns } | PatKind :: Variant { subpatterns, .. } => {
13071329 self . replace_with_fieldpats ( subpatterns)
13081330 }
@@ -1590,10 +1612,9 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
15901612 vec ! [ make_range( 0 , max) ]
15911613 }
15921614 _ 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 ] ,
15971618 }
15981619}
15991620
@@ -2152,28 +2173,31 @@ fn pat_constructor<'p, 'tcx>(
21522173 cx : & MatchCheckCtxt < ' p , ' tcx > ,
21532174 pat : & ' p Pat < ' tcx > ,
21542175) -> Constructor < ' tcx > {
2155- match * pat. kind {
2176+ match pat. kind . as_ref ( ) {
21562177 PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled by `expand_pattern`
21572178 PatKind :: Binding { .. } | PatKind :: Wild => Wildcard ,
21582179 PatKind :: Leaf { .. } | PatKind :: Deref { .. } => Single ,
2159- PatKind :: Variant { adt_def, variant_index, .. } => {
2180+ & PatKind :: Variant { adt_def, variant_index, .. } => {
21602181 Variant ( adt_def. variants [ variant_index] . def_id )
21612182 }
21622183 PatKind :: Constant { value } => {
21632184 if let Some ( int_range) = IntRange :: from_const ( cx. tcx , cx. param_env , value, pat. span ) {
21642185 IntRange ( int_range)
21652186 } else {
2166- match value . ty . kind ( ) {
2187+ match pat . ty . kind ( ) {
21672188 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) ,
21692193 // All constants that can be structurally matched have already been expanded
21702194 // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
21712195 // opaque.
21722196 _ => Opaque ,
21732197 }
21742198 }
21752199 }
2176- PatKind :: Range ( PatRange { lo, hi, end } ) => {
2200+ & PatKind :: Range ( PatRange { lo, hi, end } ) => {
21772201 let ty = lo. ty ;
21782202 if let Some ( int_range) = IntRange :: from_range (
21792203 cx. tcx ,
@@ -2188,8 +2212,7 @@ fn pat_constructor<'p, 'tcx>(
21882212 FloatRange ( lo, hi, end)
21892213 }
21902214 }
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 } => {
21932216 let array_len = match pat. ty . kind ( ) {
21942217 ty:: Array ( _, length) => Some ( length. eval_usize ( cx. tcx , cx. param_env ) ) ,
21952218 ty:: Slice ( _) => None ,
0 commit comments