@@ -309,13 +309,15 @@ pub struct MatchCheckCtxt<'a, 'tcx: 'a> {
309
309
/// outside it's module and should not be matchable with an empty match
310
310
/// statement.
311
311
pub module : DefId ,
312
+ param_env : ty:: ParamEnv < ' tcx > ,
312
313
pub pattern_arena : & ' a TypedArena < Pattern < ' tcx > > ,
313
314
pub byte_array_map : FxHashMap < * const Pattern < ' tcx > , Vec < & ' a Pattern < ' tcx > > > ,
314
315
}
315
316
316
317
impl < ' a , ' tcx > MatchCheckCtxt < ' a , ' tcx > {
317
318
pub fn create_and_enter < F , R > (
318
319
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
320
+ param_env : ty:: ParamEnv < ' tcx > ,
319
321
module : DefId ,
320
322
f : F ) -> R
321
323
where F : for < ' b > FnOnce ( MatchCheckCtxt < ' b , ' tcx > ) -> R
@@ -324,53 +326,13 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
324
326
325
327
f ( MatchCheckCtxt {
326
328
tcx,
329
+ param_env,
327
330
module,
328
331
pattern_arena : & pattern_arena,
329
332
byte_array_map : FxHashMap :: default ( ) ,
330
333
} )
331
334
}
332
335
333
- // convert a byte-string pattern to a list of u8 patterns.
334
- fn lower_byte_str_pattern < ' p > ( & mut self , pat : & ' p Pattern < ' tcx > ) -> Vec < & ' p Pattern < ' tcx > >
335
- where ' a : ' p
336
- {
337
- let pattern_arena = & * self . pattern_arena ;
338
- let tcx = self . tcx ;
339
- self . byte_array_map . entry ( pat) . or_insert_with ( || {
340
- match pat. kind {
341
- box PatternKind :: Constant {
342
- value : const_val
343
- } => {
344
- if let Some ( ptr) = const_val. to_ptr ( ) {
345
- let is_array_ptr = const_val. ty
346
- . builtin_deref ( true )
347
- . and_then ( |t| t. ty . builtin_index ( ) )
348
- . map_or ( false , |t| t == tcx. types . u8 ) ;
349
- assert ! ( is_array_ptr) ;
350
- let alloc = tcx. alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) ;
351
- assert_eq ! ( ptr. offset. bytes( ) , 0 ) ;
352
- // FIXME: check length
353
- alloc. bytes . iter ( ) . map ( |b| {
354
- & * pattern_arena. alloc ( Pattern {
355
- ty : tcx. types . u8 ,
356
- span : pat. span ,
357
- kind : box PatternKind :: Constant {
358
- value : ty:: Const :: from_bits (
359
- tcx,
360
- * b as u128 ,
361
- ty:: ParamEnv :: empty ( ) . and ( tcx. types . u8 ) )
362
- }
363
- } )
364
- } ) . collect ( )
365
- } else {
366
- bug ! ( "not a byte str: {:?}" , const_val)
367
- }
368
- }
369
- _ => span_bug ! ( pat. span, "unexpected byte array pattern {:?}" , pat)
370
- }
371
- } ) . clone ( )
372
- }
373
-
374
336
fn is_uninhabited ( & self , ty : Ty < ' tcx > ) -> bool {
375
337
if self . tcx . features ( ) . exhaustive_patterns {
376
338
self . tcx . is_ty_uninhabited_from ( self . module , ty)
@@ -1393,11 +1355,6 @@ fn slice_pat_covered_by_constructor<'tcx>(
1393
1355
ConstValue :: Scalar ( val) | ConstValue :: ScalarPair ( val, _) => val,
1394
1356
} ;
1395
1357
if let Ok ( ptr) = val. to_ptr ( ) {
1396
- let is_array_ptr = const_val. ty
1397
- . builtin_deref ( true )
1398
- . and_then ( |t| t. ty . builtin_index ( ) )
1399
- . map_or ( false , |t| t == tcx. types . u8 ) ;
1400
- assert ! ( is_array_ptr) ;
1401
1358
tcx. alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) . bytes . as_ref ( )
1402
1359
} else {
1403
1360
bug ! ( "unexpected non-ptr ConstantValue" )
@@ -1705,26 +1662,63 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
1705
1662
PatternKind :: Constant { value } => {
1706
1663
match * constructor {
1707
1664
Slice ( ..) => {
1708
- if let Some ( ptr) = value. to_ptr ( ) {
1709
- let is_array_ptr = value. ty
1710
- . builtin_deref ( true )
1711
- . and_then ( |t| t. ty . builtin_index ( ) )
1712
- . map_or ( false , |t| t == cx. tcx . types . u8 ) ;
1713
- assert ! ( is_array_ptr) ;
1714
- let data_len = cx. tcx
1715
- . alloc_map
1716
- . lock ( )
1717
- . unwrap_memory ( ptr. alloc_id )
1718
- . bytes
1719
- . len ( ) ;
1720
- if wild_patterns. len ( ) == data_len {
1721
- Some ( cx. lower_byte_str_pattern ( pat) )
1722
- } else {
1723
- None
1665
+ // we extract an `Option` for the pointer because slices of zero elements don't
1666
+ // necessarily point to memory, they are usually just integers. The only time
1667
+ // they should be pointing to memory is when they are subslices of nonzero
1668
+ // slices
1669
+ let ( opt_ptr, n, ty) = match value. ty . builtin_deref ( false ) . unwrap ( ) . ty . sty {
1670
+ ty:: TyKind :: Array ( t, n) => ( value. to_ptr ( ) , n. unwrap_usize ( cx. tcx ) , t) ,
1671
+ ty:: TyKind :: Slice ( t) => {
1672
+ match value. val {
1673
+ ConstValue :: ScalarPair ( ptr, n) => (
1674
+ ptr. to_ptr ( ) . ok ( ) ,
1675
+ n. to_bits ( cx. tcx . data_layout . pointer_size ) . unwrap ( ) as u64 ,
1676
+ t,
1677
+ ) ,
1678
+ _ => span_bug ! (
1679
+ pat. span,
1680
+ "slice pattern constant must be scalar pair but is {:?}" ,
1681
+ value,
1682
+ ) ,
1683
+ }
1684
+ } ,
1685
+ _ => span_bug ! (
1686
+ pat. span,
1687
+ "unexpected const-val {:?} with ctor {:?}" ,
1688
+ value,
1689
+ constructor,
1690
+ ) ,
1691
+ } ;
1692
+ if wild_patterns. len ( ) as u64 == n {
1693
+ // convert a constant slice/array pattern to a list of patterns.
1694
+ match ( n, opt_ptr) {
1695
+ ( 0 , _) => Some ( Vec :: new ( ) ) ,
1696
+ ( _, Some ( ptr) ) => {
1697
+ let alloc = cx. tcx . alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) ;
1698
+ let layout = cx. tcx . layout_of ( cx. param_env . and ( ty) ) . ok ( ) ?;
1699
+ ( 0 ..n) . map ( |i| {
1700
+ let ptr = ptr. offset ( layout. size * i, & cx. tcx ) . ok ( ) ?;
1701
+ let scalar = alloc. read_scalar (
1702
+ & cx. tcx , ptr, layout. size ,
1703
+ ) . ok ( ) ?;
1704
+ let scalar = scalar. not_undef ( ) . ok ( ) ?;
1705
+ let value = ty:: Const :: from_scalar ( cx. tcx , scalar, ty) ;
1706
+ let pattern = Pattern {
1707
+ ty,
1708
+ span : pat. span ,
1709
+ kind : box PatternKind :: Constant { value } ,
1710
+ } ;
1711
+ Some ( & * cx. pattern_arena . alloc ( pattern) )
1712
+ } ) . collect ( )
1713
+ } ,
1714
+ ( _, None ) => span_bug ! (
1715
+ pat. span,
1716
+ "non zero length slice with const-val {:?}" ,
1717
+ value,
1718
+ ) ,
1724
1719
}
1725
1720
} else {
1726
- span_bug ! ( pat. span,
1727
- "unexpected const-val {:?} with ctor {:?}" , value, constructor)
1721
+ None
1728
1722
}
1729
1723
}
1730
1724
_ => {
0 commit comments