@@ -209,10 +209,16 @@ struct LiteralExpander<'a, 'tcx> {
209209
210210impl < ' a , ' tcx > LiteralExpander < ' a , ' tcx > {
211211 /// Derefs `val` and potentially unsizes the value if `crty` is an array and `rty` a slice
212+ ///
213+ /// `crty` and `rty` can differ because you can use array constants in the presence of slice
214+ /// patterns. So the pattern may end up being a slice, but the constant is an array. We convert
215+ /// the array to a slice in that case
212216 fn fold_const_value_deref (
213217 & mut self ,
214218 val : ConstValue < ' tcx > ,
219+ // the pattern's pointee type
215220 rty : Ty < ' tcx > ,
221+ // the constant's pointee type
216222 crty : Ty < ' tcx > ,
217223 ) -> ConstValue < ' tcx > {
218224 match ( val, & crty. sty , & rty. sty ) {
@@ -776,6 +782,7 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
776782 for row in patterns {
777783 match * row. kind {
778784 PatternKind :: Constant { value } => {
785+ // extract the length of an array/slice from a constant
779786 match ( value. val , & value. ty . sty ) {
780787 ( _, ty:: Array ( _, n) ) => max_fixed_len = cmp:: max (
781788 max_fixed_len,
@@ -1393,53 +1400,55 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
13931400 }
13941401}
13951402
1396- fn slice_pat_covered_by_constructor < ' tcx > (
1403+ // checks whether a constant is equal to a user-written slice pattern. Only supports byte slices,
1404+ // meaning all other types will compare unequal and thus equal patterns often do not cause the
1405+ // second pattern to lint about unreachable match arms.
1406+ fn slice_pat_covered_by_const < ' tcx > (
13971407 tcx : TyCtxt < ' _ , ' tcx , ' _ > ,
13981408 _span : Span ,
1399- ctor : & Constructor ,
1409+ const_val : & ty :: Const < ' tcx > ,
14001410 prefix : & [ Pattern < ' tcx > ] ,
14011411 slice : & Option < Pattern < ' tcx > > ,
14021412 suffix : & [ Pattern < ' tcx > ]
14031413) -> Result < bool , ErrorReported > {
1404- let data: & [ u8 ] = match * ctor {
1405- ConstantValue ( const_val) => {
1406- match ( const_val. val , & const_val. ty . sty ) {
1407- ( ConstValue :: ByRef ( id, alloc, offset) , ty:: Array ( t, n) ) => {
1408- if * t != tcx. types . u8 {
1409- // FIXME(oli-obk): can't mix const patterns with slice patterns and get
1410- // any sort of exhaustiveness/unreachable check yet
1411- return Ok ( false ) ;
1412- }
1413- let ptr = Pointer :: new ( id, offset) ;
1414- let n = n. assert_usize ( tcx) . unwrap ( ) ;
1415- alloc. get_bytes ( & tcx, ptr, Size :: from_bytes ( n) ) . unwrap ( )
1416- } ,
1417- ( ConstValue :: ScalarPair ( Scalar :: Bits { .. } , n) , ty:: Slice ( _) ) => {
1418- assert_eq ! ( n. to_usize( & tcx) . unwrap( ) , 0 ) ;
1419- & [ ]
1420- } ,
1421- ( ConstValue :: ScalarPair ( Scalar :: Ptr ( ptr) , n) , ty:: Slice ( t) ) => {
1422- if * t != tcx. types . u8 {
1423- // FIXME(oli-obk): can't mix const patterns with slice patterns and get
1424- // any sort of exhaustiveness/unreachable check yet
1425- return Ok ( false ) ;
1426- }
1427- let n = n. to_usize ( & tcx) . unwrap ( ) ;
1428- tcx. alloc_map
1429- . lock ( )
1430- . unwrap_memory ( ptr. alloc_id )
1431- . get_bytes ( & tcx, ptr, Size :: from_bytes ( n) )
1432- . unwrap ( )
1433- } ,
1434- _ => bug ! (
1435- "slice_pat_covered_by_constructor: {:#?}, {:#?}, {:#?}, {:#?}" ,
1436- ctor, prefix, slice, suffix,
1437- ) ,
1414+ let data: & [ u8 ] = match ( const_val. val , & const_val. ty . sty ) {
1415+ ( ConstValue :: ByRef ( id, alloc, offset) , ty:: Array ( t, n) ) => {
1416+ if * t != tcx. types . u8 {
1417+ // FIXME(oli-obk): can't mix const patterns with slice patterns and get
1418+ // any sort of exhaustiveness/unreachable check yet
1419+ return Ok ( false ) ;
14381420 }
1439- }
1421+ let ptr = Pointer :: new ( id, offset) ;
1422+ let n = n. assert_usize ( tcx) . unwrap ( ) ;
1423+ alloc. get_bytes ( & tcx, ptr, Size :: from_bytes ( n) ) . unwrap ( )
1424+ } ,
1425+ // a slice fat pointer to a zero length slice
1426+ ( ConstValue :: ScalarPair ( Scalar :: Bits { .. } , n) , ty:: Slice ( t) ) => {
1427+ if * t != tcx. types . u8 {
1428+ // FIXME(oli-obk): can't mix const patterns with slice patterns and get
1429+ // any sort of exhaustiveness/unreachable check yet
1430+ return Ok ( false ) ;
1431+ }
1432+ assert_eq ! ( n. to_usize( & tcx) . unwrap( ) , 0 ) ;
1433+ & [ ]
1434+ } ,
1435+ //
1436+ ( ConstValue :: ScalarPair ( Scalar :: Ptr ( ptr) , n) , ty:: Slice ( t) ) => {
1437+ if * t != tcx. types . u8 {
1438+ // FIXME(oli-obk): can't mix const patterns with slice patterns and get
1439+ // any sort of exhaustiveness/unreachable check yet
1440+ return Ok ( false ) ;
1441+ }
1442+ let n = n. to_usize ( & tcx) . unwrap ( ) ;
1443+ tcx. alloc_map
1444+ . lock ( )
1445+ . unwrap_memory ( ptr. alloc_id )
1446+ . get_bytes ( & tcx, ptr, Size :: from_bytes ( n) )
1447+ . unwrap ( )
1448+ } ,
14401449 _ => bug ! (
1441- "slice_pat_covered_by_constructor not ConstValue : {:#?}, {:#?}, {:#?}, {:#?}" ,
1442- ctor , prefix, slice, suffix,
1450+ "slice_pat_covered_by_const : {:#?}, {:#?}, {:#?}, {:#?}" ,
1451+ const_val , prefix, slice, suffix,
14431452 ) ,
14441453 } ;
14451454
@@ -1837,9 +1846,9 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
18371846 None
18381847 }
18391848 }
1840- ConstantValue ( .. ) => {
1841- match slice_pat_covered_by_constructor (
1842- cx. tcx , pat. span , constructor , prefix, slice, suffix
1849+ ConstantValue ( cv ) => {
1850+ match slice_pat_covered_by_const (
1851+ cx. tcx , pat. span , cv , prefix, slice, suffix
18431852 ) {
18441853 Ok ( true ) => Some ( smallvec ! [ ] ) ,
18451854 Ok ( false ) => None ,
0 commit comments