@@ -18,22 +18,20 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
18
18
/// Converts an evaluated constant to a pattern (if possible).
19
19
/// This means aggregate values (like structs and enums) are converted
20
20
/// to a pattern that matches the value (as if you'd compared via structural equality).
21
+ #[ instrument( skip( self ) ) ]
21
22
pub ( super ) fn const_to_pat (
22
23
& self ,
23
24
cv : & ' tcx ty:: Const < ' tcx > ,
24
25
id : hir:: HirId ,
25
26
span : Span ,
26
27
mir_structural_match_violation : bool ,
27
28
) -> Pat < ' tcx > {
28
- debug ! ( "const_to_pat: cv={:#?} id={:?}" , cv, id) ;
29
- debug ! ( "const_to_pat: cv.ty={:?} span={:?}" , cv. ty, span) ;
30
-
31
29
let pat = self . tcx . infer_ctxt ( ) . enter ( |infcx| {
32
30
let mut convert = ConstToPat :: new ( self , id, span, infcx) ;
33
31
convert. to_pat ( cv, mir_structural_match_violation)
34
32
} ) ;
35
33
36
- debug ! ( "const_to_pat: pat={:?}" , pat) ;
34
+ debug ! ( ? pat) ;
37
35
pat
38
36
}
39
37
}
@@ -61,6 +59,8 @@ struct ConstToPat<'a, 'tcx> {
61
59
infcx : InferCtxt < ' a , ' tcx > ,
62
60
63
61
include_lint_checks : bool ,
62
+
63
+ treat_byte_string_as_slice : bool ,
64
64
}
65
65
66
66
mod fallback_to_const_ref {
@@ -88,6 +88,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
88
88
span : Span ,
89
89
infcx : InferCtxt < ' a , ' tcx > ,
90
90
) -> Self {
91
+ trace ! ( ?pat_ctxt. typeck_results. hir_owner) ;
91
92
ConstToPat {
92
93
id,
93
94
span,
@@ -97,6 +98,10 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
97
98
saw_const_match_error : Cell :: new ( false ) ,
98
99
saw_const_match_lint : Cell :: new ( false ) ,
99
100
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 ) ,
100
105
}
101
106
}
102
107
@@ -153,6 +158,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
153
158
cv : & ' tcx ty:: Const < ' tcx > ,
154
159
mir_structural_match_violation : bool ,
155
160
) -> Pat < ' tcx > {
161
+ trace ! ( self . treat_byte_string_as_slice) ;
156
162
// This method is just a wrapper handling a validity check; the heavy lifting is
157
163
// performed by the recursive `recur` method, which is not meant to be
158
164
// invoked except by this method.
@@ -384,7 +390,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
384
390
}
385
391
PatKind :: Wild
386
392
}
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
388
394
// optimization for now.
389
395
ty:: Str => PatKind :: Constant { value : cv } ,
390
396
// `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> {
393
399
// as slices. This means we turn `&[T; N]` constants into slice patterns, which
394
400
// has no negative effects on pattern matching, even if we're actually matching on
395
401
// 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, _) |
397
425
// Cannot merge this with the catch all branch below, because the `const_deref`
398
426
// changes the type from slice to array, we need to keep the original type in the
399
427
// pattern.
400
- ty:: Slice ( .. ) => {
428
+ ty:: Slice ( elem_ty ) => {
401
429
let old = self . behind_reference . replace ( true ) ;
402
430
let array = tcx. deref_const ( self . param_env . and ( cv) ) ;
403
431
let val = PatKind :: Deref {
@@ -413,7 +441,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
413
441
suffix : vec ! [ ] ,
414
442
} ) ,
415
443
span,
416
- ty : pointee_ty ,
444
+ ty : tcx . mk_slice ( elem_ty ) ,
417
445
} ,
418
446
} ;
419
447
self . behind_reference . set ( old) ;
0 commit comments