@@ -18,22 +18,20 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
1818    /// Converts an evaluated constant to a pattern (if possible). 
1919/// This means aggregate values (like structs and enums) are converted 
2020/// to a pattern that matches the value (as if you'd compared via structural equality). 
21+ #[ instrument( skip( self ) ) ]  
2122    pub ( super )  fn  const_to_pat ( 
2223        & self , 
2324        cv :  & ' tcx  ty:: Const < ' tcx > , 
2425        id :  hir:: HirId , 
2526        span :  Span , 
2627        mir_structural_match_violation :  bool , 
2728    )  -> Pat < ' tcx >  { 
28-         debug ! ( "const_to_pat: cv={:#?} id={:?}" ,  cv,  id) ; 
29-         debug ! ( "const_to_pat: cv.ty={:?} span={:?}" ,  cv. ty,  span) ; 
30- 
3129        let  pat = self . tcx . infer_ctxt ( ) . enter ( |infcx| { 
3230            let  mut  convert = ConstToPat :: new ( self ,  id,  span,  infcx) ; 
3331            convert. to_pat ( cv,  mir_structural_match_violation) 
3432        } ) ; 
3533
36-         debug ! ( "const_to_pat: pat={:?}" ,   pat) ; 
34+         debug ! ( ? pat) ; 
3735        pat
3836    } 
3937} 
@@ -61,6 +59,8 @@ struct ConstToPat<'a, 'tcx> {
6159    infcx :  InferCtxt < ' a ,  ' tcx > , 
6260
6361    include_lint_checks :  bool , 
62+ 
63+     treat_byte_string_as_slice :  bool , 
6464} 
6565
6666mod  fallback_to_const_ref { 
@@ -88,6 +88,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
8888        span :  Span , 
8989        infcx :  InferCtxt < ' a ,  ' tcx > , 
9090    )  -> Self  { 
91+         trace ! ( ?pat_ctxt. typeck_results. hir_owner) ; 
9192        ConstToPat  { 
9293            id, 
9394            span, 
@@ -97,6 +98,10 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
9798            saw_const_match_error :  Cell :: new ( false ) , 
9899            saw_const_match_lint :  Cell :: new ( false ) , 
99100            behind_reference :  Cell :: new ( false ) , 
101+             treat_byte_string_as_slice :  pat_ctxt
102+                 . typeck_results 
103+                 . treat_byte_string_as_slice 
104+                 . contains ( & id. local_id ) , 
100105        } 
101106    } 
102107
@@ -153,6 +158,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
153158        cv :  & ' tcx  ty:: Const < ' tcx > , 
154159        mir_structural_match_violation :  bool , 
155160    )  -> Pat < ' tcx >  { 
161+         trace ! ( self . treat_byte_string_as_slice) ; 
156162        // This method is just a wrapper handling a validity check; the heavy lifting is 
157163        // performed by the recursive `recur` method, which is not meant to be 
158164        // invoked except by this method. 
@@ -384,7 +390,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
384390                    } 
385391                    PatKind :: Wild 
386392                } 
387-                 // `&str` and `&[u8]` are  represented as `ConstValue::Slice`, let's keep using this 
393+                 // `&str` is  represented as `ConstValue::Slice`, let's keep using this 
388394                // optimization for now. 
389395                ty:: Str  => PatKind :: Constant  {  value :  cv } , 
390396                // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when 
@@ -393,11 +399,33 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
393399                // as slices. This means we turn `&[T; N]` constants into slice patterns, which 
394400                // has no negative effects on pattern matching, even if we're actually matching on 
395401                // arrays. 
396-                 ty:: Array ( ..)  |
402+                 ty:: Array ( ..)  if  !self . treat_byte_string_as_slice  => { 
403+                     let  old = self . behind_reference . replace ( true ) ; 
404+                     let  array = tcx. deref_const ( self . param_env . and ( cv) ) ; 
405+                     let  val = PatKind :: Deref  { 
406+                         subpattern :  Pat  { 
407+                             kind :  Box :: new ( PatKind :: Array  { 
408+                                 prefix :  tcx
409+                                     . destructure_const ( param_env. and ( array) ) 
410+                                     . fields 
411+                                     . iter ( ) 
412+                                     . map ( |val| self . recur ( val,  false ) ) 
413+                                     . collect :: < Result < _ ,  _ > > ( ) ?, 
414+                                 slice :  None , 
415+                                 suffix :  vec ! [ ] , 
416+                             } ) , 
417+                             span, 
418+                             ty :  pointee_ty, 
419+                         } , 
420+                     } ; 
421+                     self . behind_reference . set ( old) ; 
422+                     val
423+                 } 
424+                 ty:: Array ( elem_ty,  _)  |
397425                // Cannot merge this with the catch all branch below, because the `const_deref` 
398426                // changes the type from slice to array, we need to keep the original type in the 
399427                // pattern. 
400-                 ty:: Slice ( .. )  => { 
428+                 ty:: Slice ( elem_ty )  => { 
401429                    let  old = self . behind_reference . replace ( true ) ; 
402430                    let  array = tcx. deref_const ( self . param_env . and ( cv) ) ; 
403431                    let  val = PatKind :: Deref  { 
@@ -413,7 +441,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
413441                                suffix :  vec ! [ ] , 
414442                            } ) , 
415443                            span, 
416-                             ty :  pointee_ty , 
444+                             ty :  tcx . mk_slice ( elem_ty ) , 
417445                        } , 
418446                    } ; 
419447                    self . behind_reference . set ( old) ; 
0 commit comments