@@ -359,6 +359,15 @@ impl<'tcx> ConstToPat<'tcx> {
359359 def. non_enum_variant ( ) . fields . iter ( ) . map ( |field| field. ty ( self . tcx ( ) , substs) ) ,
360360 ) ) ?,
361361 } ,
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+ } ,
362371 ty:: Array ( elem_ty, _) => PatKind :: Array {
363372 prefix : cv
364373 . unwrap_branch ( )
@@ -372,70 +381,16 @@ impl<'tcx> ConstToPat<'tcx> {
372381 // `&str` is represented as a valtree, let's keep using this
373382 // optimization for now.
374383 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- }
427384 // Backwards compatibility hack: support references to non-structural types,
428385 // but hard error if we aren't behind a double reference. We could just use
429386 // the fallback code path below, but that would allow *more* of this fishy
430387 // code to compile, as then it only goes through the future incompat lint
431388 // instead of a hard error.
432389 ty:: Adt ( _, _) if !self . type_marked_structural ( * pointee_ty) => {
433390 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 (
439394 lint:: builtin:: INDIRECT_STRUCTURAL_MATCH ,
440395 self . id ,
441396 span,
@@ -456,16 +411,28 @@ impl<'tcx> ConstToPat<'tcx> {
456411 // convert the dereferenced constant to a pattern that is the sub-pattern of the
457412 // deref pattern.
458413 _ => {
459- if !pointee_ty. is_sized ( tcx, param_env) {
414+ if !pointee_ty. is_sized ( tcx, param_env) && !pointee_ty . is_slice ( ) {
460415 let err = UnsizedPattern { span, non_sm_ty : * pointee_ty } ;
461416 tcx. sess . emit_err ( err) ;
462417
463418 // FIXME: introduce PatKind::Error to silence follow up diagnostics due to unreachable patterns.
464419 PatKind :: Wild
465420 } else {
466421 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+ } ;
467434 // 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 ) ?;
469436 self . behind_reference . set ( old) ;
470437 PatKind :: Deref { subpattern }
471438 }
0 commit comments