@@ -359,6 +359,15 @@ impl<'tcx> ConstToPat<'tcx> {
359
359
def. non_enum_variant ( ) . fields . iter ( ) . map ( |field| field. ty ( self . tcx ( ) , substs) ) ,
360
360
) ) ?,
361
361
} ,
362
+ ty:: Slice ( elem_ty) => PatKind :: Slice {
363
+ prefix : cv
364
+ . unwrap_branch ( )
365
+ . iter ( )
366
+ . map ( |val| self . recur ( * val, * elem_ty, false ) )
367
+ . collect :: < Result < _ , _ > > ( ) ?,
368
+ slice : None ,
369
+ suffix : Box :: new ( [ ] ) ,
370
+ } ,
362
371
ty:: Array ( elem_ty, _) => PatKind :: Array {
363
372
prefix : cv
364
373
. unwrap_branch ( )
@@ -372,70 +381,16 @@ impl<'tcx> ConstToPat<'tcx> {
372
381
// `&str` is represented as a valtree, let's keep using this
373
382
// optimization for now.
374
383
ty:: Str => PatKind :: Constant { value : mir:: ConstantKind :: Ty ( tcx. mk_const ( cv, ty) ) } ,
375
- // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
376
- // matching against references, you can only use byte string literals.
377
- // The typechecker has a special case for byte string literals, by treating them
378
- // as slices. This means we turn `&[T; N]` constants into slice patterns, which
379
- // has no negative effects on pattern matching, even if we're actually matching on
380
- // arrays.
381
- ty:: Array ( elem_ty, _) if !self . treat_byte_string_as_slice => {
382
- let old = self . behind_reference . replace ( true ) ;
383
- // References have the same valtree representation as their pointee.
384
- let array = cv;
385
- let val = PatKind :: Deref {
386
- subpattern : Box :: new ( Pat {
387
- kind : PatKind :: Array {
388
- prefix : array. unwrap_branch ( )
389
- . iter ( )
390
- . map ( |val| self . recur ( * val, elem_ty, false ) )
391
- . collect :: < Result < _ , _ > > ( ) ?,
392
- slice : None ,
393
- suffix : Box :: new ( [ ] ) ,
394
- } ,
395
- span,
396
- ty : tcx. mk_slice ( elem_ty) ,
397
- } ) ,
398
- } ;
399
- self . behind_reference . set ( old) ;
400
- val
401
- }
402
- ty:: Array ( elem_ty, _) |
403
- // Cannot merge this with the catch all branch below, because the `const_deref`
404
- // changes the type from slice to array, we need to keep the original type in the
405
- // pattern.
406
- ty:: Slice ( elem_ty) => {
407
- let old = self . behind_reference . replace ( true ) ;
408
- // References have the same valtree representation as their pointee.
409
- let array = cv;
410
- let val = PatKind :: Deref {
411
- subpattern : Box :: new ( Pat {
412
- kind : PatKind :: Slice {
413
- prefix : array. unwrap_branch ( )
414
- . iter ( )
415
- . map ( |val| self . recur ( * val, elem_ty, false ) )
416
- . collect :: < Result < _ , _ > > ( ) ?,
417
- slice : None ,
418
- suffix : Box :: new ( [ ] ) ,
419
- } ,
420
- span,
421
- ty : tcx. mk_slice ( elem_ty) ,
422
- } ) ,
423
- } ;
424
- self . behind_reference . set ( old) ;
425
- val
426
- }
427
384
// Backwards compatibility hack: support references to non-structural types,
428
385
// but hard error if we aren't behind a double reference. We could just use
429
386
// the fallback code path below, but that would allow *more* of this fishy
430
387
// code to compile, as then it only goes through the future incompat lint
431
388
// instead of a hard error.
432
389
ty:: Adt ( _, _) if !self . type_marked_structural ( * pointee_ty) => {
433
390
if self . behind_reference . get ( ) {
434
- if !self . saw_const_match_error . get ( )
435
- && !self . saw_const_match_lint . get ( )
436
- {
437
- self . saw_const_match_lint . set ( true ) ;
438
- tcx. emit_spanned_lint (
391
+ if !self . saw_const_match_error . get ( ) && !self . saw_const_match_lint . get ( ) {
392
+ self . saw_const_match_lint . set ( true ) ;
393
+ tcx. emit_spanned_lint (
439
394
lint:: builtin:: INDIRECT_STRUCTURAL_MATCH ,
440
395
self . id ,
441
396
span,
@@ -456,16 +411,28 @@ impl<'tcx> ConstToPat<'tcx> {
456
411
// convert the dereferenced constant to a pattern that is the sub-pattern of the
457
412
// deref pattern.
458
413
_ => {
459
- if !pointee_ty. is_sized ( tcx, param_env) {
414
+ if !pointee_ty. is_sized ( tcx, param_env) && !pointee_ty . is_slice ( ) {
460
415
let err = UnsizedPattern { span, non_sm_ty : * pointee_ty } ;
461
416
tcx. sess . emit_err ( err) ;
462
417
463
418
// FIXME: introduce PatKind::Error to silence follow up diagnostics due to unreachable patterns.
464
419
PatKind :: Wild
465
420
} else {
466
421
let old = self . behind_reference . replace ( true ) ;
422
+ // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
423
+ // matching against references, you can only use byte string literals.
424
+ // The typechecker has a special case for byte string literals, by treating them
425
+ // as slices. This means we turn `&[T; N]` constants into slice patterns, which
426
+ // has no negative effects on pattern matching, even if we're actually matching on
427
+ // arrays.
428
+ let pointee_ty = match * pointee_ty. kind ( ) {
429
+ ty:: Array ( elem_ty, _) if self . treat_byte_string_as_slice => {
430
+ tcx. mk_slice ( elem_ty)
431
+ }
432
+ _ => * pointee_ty,
433
+ } ;
467
434
// References have the same valtree representation as their pointee.
468
- let subpattern = self . recur ( cv, * pointee_ty, false ) ?;
435
+ let subpattern = self . recur ( cv, pointee_ty, false ) ?;
469
436
self . behind_reference . set ( old) ;
470
437
PatKind :: Deref { subpattern }
471
438
}
0 commit comments