@@ -209,10 +209,16 @@ struct LiteralExpander<'a, 'tcx> {
209
209
210
210
impl < ' a , ' tcx > LiteralExpander < ' a , ' tcx > {
211
211
/// 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
212
216
fn fold_const_value_deref (
213
217
& mut self ,
214
218
val : ConstValue < ' tcx > ,
219
+ // the pattern's pointee type
215
220
rty : Ty < ' tcx > ,
221
+ // the constant's pointee type
216
222
crty : Ty < ' tcx > ,
217
223
) -> ConstValue < ' tcx > {
218
224
match ( val, & crty. sty , & rty. sty ) {
@@ -776,6 +782,7 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
776
782
for row in patterns {
777
783
match * row. kind {
778
784
PatternKind :: Constant { value } => {
785
+ // extract the length of an array/slice from a constant
779
786
match ( value. val , & value. ty . sty ) {
780
787
( _, ty:: Array ( _, n) ) => max_fixed_len = cmp:: max (
781
788
max_fixed_len,
@@ -1393,53 +1400,55 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
1393
1400
}
1394
1401
}
1395
1402
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 > (
1397
1407
tcx : TyCtxt < ' _ , ' tcx , ' _ > ,
1398
1408
_span : Span ,
1399
- ctor : & Constructor ,
1409
+ const_val : & ty :: Const < ' tcx > ,
1400
1410
prefix : & [ Pattern < ' tcx > ] ,
1401
1411
slice : & Option < Pattern < ' tcx > > ,
1402
1412
suffix : & [ Pattern < ' tcx > ]
1403
1413
) -> 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 ) ;
1438
1420
}
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
+ } ,
1440
1449
_ => 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,
1443
1452
) ,
1444
1453
} ;
1445
1454
@@ -1837,9 +1846,9 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
1837
1846
None
1838
1847
}
1839
1848
}
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
1843
1852
) {
1844
1853
Ok ( true ) => Some ( smallvec ! [ ] ) ,
1845
1854
Ok ( false ) => None ,
0 commit comments