@@ -309,13 +309,15 @@ pub struct MatchCheckCtxt<'a, 'tcx: 'a> {
309309 /// outside it's module and should not be matchable with an empty match
310310 /// statement.
311311 pub module : DefId ,
312+ param_env : ty:: ParamEnv < ' tcx > ,
312313 pub pattern_arena : & ' a TypedArena < Pattern < ' tcx > > ,
313314 pub byte_array_map : FxHashMap < * const Pattern < ' tcx > , Vec < & ' a Pattern < ' tcx > > > ,
314315}
315316
316317impl < ' a , ' tcx > MatchCheckCtxt < ' a , ' tcx > {
317318 pub fn create_and_enter < F , R > (
318319 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
320+ param_env : ty:: ParamEnv < ' tcx > ,
319321 module : DefId ,
320322 f : F ) -> R
321323 where F : for < ' b > FnOnce ( MatchCheckCtxt < ' b , ' tcx > ) -> R
@@ -324,53 +326,13 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
324326
325327 f ( MatchCheckCtxt {
326328 tcx,
329+ param_env,
327330 module,
328331 pattern_arena : & pattern_arena,
329332 byte_array_map : FxHashMap :: default ( ) ,
330333 } )
331334 }
332335
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-
374336 fn is_uninhabited ( & self , ty : Ty < ' tcx > ) -> bool {
375337 if self . tcx . features ( ) . exhaustive_patterns {
376338 self . tcx . is_ty_uninhabited_from ( self . module , ty)
@@ -1393,11 +1355,6 @@ fn slice_pat_covered_by_constructor<'tcx>(
13931355 ConstValue :: Scalar ( val) | ConstValue :: ScalarPair ( val, _) => val,
13941356 } ;
13951357 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) ;
14011358 tcx. alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) . bytes . as_ref ( )
14021359 } else {
14031360 bug ! ( "unexpected non-ptr ConstantValue" )
@@ -1705,26 +1662,63 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
17051662 PatternKind :: Constant { value } => {
17061663 match * constructor {
17071664 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+ ) ,
17241719 }
17251720 } else {
1726- span_bug ! ( pat. span,
1727- "unexpected const-val {:?} with ctor {:?}" , value, constructor)
1721+ None
17281722 }
17291723 }
17301724 _ => {
0 commit comments