@@ -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 }
@@ -788,7 +802,7 @@ enum Constructor<'tcx> {
788802 /// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
789803 NonExhaustive ,
790804 /// Fake constructor for those types for which we can't list constructors explicitly, like
791- /// `f64` and `& str`.
805+ /// `f64` and `str`.
792806 Unlistable ,
793807 /// Wildcard pattern.
794808 Wildcard ,
@@ -931,7 +945,12 @@ impl<'tcx> Constructor<'tcx> {
931945 // Otherwise, only a wildcard pattern can match the special extra constructor.
932946 ( Unlistable , _) => false ,
933947
934- _ => bug ! ( "trying to compare incompatible constructors {:?} and {:?}" , self , other) ,
948+ _ => span_bug ! (
949+ pcx. span,
950+ "trying to compare incompatible constructors {:?} and {:?}" ,
951+ self ,
952+ other
953+ ) ,
935954 }
936955 }
937956
@@ -1009,6 +1028,10 @@ impl<'tcx> Constructor<'tcx> {
10091028 PatKind :: Leaf { subpatterns }
10101029 }
10111030 }
1031+ // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
1032+ // be careful to reconstruct the correct constant pattern here. However a string
1033+ // literal pattern will never be reported as a non-exhaustiveness witness, so we
1034+ // can ignore this issue.
10121035 ty:: Ref ( ..) => PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) } ,
10131036 ty:: Slice ( _) | ty:: Array ( ..) => bug ! ( "bad slice pattern {:?} {:?}" , self , pcx. ty) ,
10141037 _ => PatKind :: Wild ,
@@ -1303,9 +1326,13 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
13031326 /// [Some(0), ..] => {}
13041327 /// }
13051328 /// ```
1329+ /// This is guaranteed to preserve the number of patterns in `self`.
13061330 fn replace_with_pattern_arguments ( & self , pat : & ' p Pat < ' tcx > ) -> Self {
13071331 match pat. kind . as_ref ( ) {
1308- PatKind :: Deref { subpattern } => Self :: from_single_pattern ( subpattern) ,
1332+ PatKind :: Deref { subpattern } => {
1333+ assert_eq ! ( self . len( ) , 1 ) ;
1334+ Fields :: from_single_pattern ( subpattern)
1335+ }
13091336 PatKind :: Leaf { subpatterns } | PatKind :: Variant { subpatterns, .. } => {
13101337 self . replace_with_fieldpats ( subpatterns)
13111338 }
@@ -1596,9 +1623,8 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
15961623 vec ! [ make_range( 0 , max) ]
15971624 }
15981625 _ if cx. is_uninhabited ( pcx. ty ) => vec ! [ ] ,
1599- ty:: Adt ( ..) | ty:: Tuple ( ..) => vec ! [ Single ] ,
1600- ty:: Ref ( _, t, _) if !t. is_str ( ) => vec ! [ Single ] ,
1601- // This type is one for which we don't know how to list constructors, like `&str` or `f64`.
1626+ ty:: Adt ( ..) | ty:: Tuple ( ..) | ty:: Ref ( ..) => vec ! [ Single ] ,
1627+ // This type is one for which we don't know how to list constructors, like `str` or `f64`.
16021628 _ => vec ! [ Unlistable ] ,
16031629 }
16041630}
@@ -2161,28 +2187,31 @@ fn pat_constructor<'p, 'tcx>(
21612187 cx : & MatchCheckCtxt < ' p , ' tcx > ,
21622188 pat : & ' p Pat < ' tcx > ,
21632189) -> Constructor < ' tcx > {
2164- match * pat. kind {
2190+ match pat. kind . as_ref ( ) {
21652191 PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled by `expand_pattern`
21662192 PatKind :: Binding { .. } | PatKind :: Wild => Wildcard ,
21672193 PatKind :: Leaf { .. } | PatKind :: Deref { .. } => Single ,
2168- PatKind :: Variant { adt_def, variant_index, .. } => {
2194+ & PatKind :: Variant { adt_def, variant_index, .. } => {
21692195 Variant ( adt_def. variants [ variant_index] . def_id )
21702196 }
21712197 PatKind :: Constant { value } => {
21722198 if let Some ( int_range) = IntRange :: from_const ( cx. tcx , cx. param_env , value, pat. span ) {
21732199 IntRange ( int_range)
21742200 } else {
2175- match value . ty . kind ( ) {
2201+ match pat . ty . kind ( ) {
21762202 ty:: Float ( _) => FloatRange ( value, value, RangeEnd :: Included ) ,
2177- ty:: Ref ( _, t, _) if t. is_str ( ) => Str ( value) ,
2203+ // In `expand_pattern`, we convert string literals to `&CONST` patterns with
2204+ // `CONST` a pattern of type `str`. In truth this contains a constant of type
2205+ // `&str`.
2206+ ty:: Str => Str ( value) ,
21782207 // All constants that can be structurally matched have already been expanded
21792208 // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
21802209 // opaque.
21812210 _ => Opaque ,
21822211 }
21832212 }
21842213 }
2185- PatKind :: Range ( PatRange { lo, hi, end } ) => {
2214+ & PatKind :: Range ( PatRange { lo, hi, end } ) => {
21862215 let ty = lo. ty ;
21872216 if let Some ( int_range) = IntRange :: from_range (
21882217 cx. tcx ,
@@ -2197,8 +2226,7 @@ fn pat_constructor<'p, 'tcx>(
21972226 FloatRange ( lo, hi, end)
21982227 }
21992228 }
2200- PatKind :: Array { ref prefix, ref slice, ref suffix }
2201- | PatKind :: Slice { ref prefix, ref slice, ref suffix } => {
2229+ PatKind :: Array { prefix, slice, suffix } | PatKind :: Slice { prefix, slice, suffix } => {
22022230 let array_len = match pat. ty . kind ( ) {
22032231 ty:: Array ( _, length) => Some ( length. eval_usize ( cx. tcx , cx. param_env ) ) ,
22042232 ty:: Slice ( _) => None ,
0 commit comments