@@ -237,11 +237,11 @@ use super::{FieldPat, Pat, PatKind, PatRange};
237237
238238use rustc:: hir:: def_id:: DefId ;
239239use rustc:: hir:: { HirId , RangeEnd } ;
240- use rustc:: ty:: layout:: { Integer , IntegerExt , Size , VariantIdx } ;
240+ use rustc:: ty:: layout:: { Align , Integer , IntegerExt , Size , VariantIdx } ;
241241use rustc:: ty:: { self , Const , Ty , TyCtxt , TypeFoldable , VariantDef } ;
242242
243243use rustc:: lint;
244- use rustc:: mir:: interpret:: { truncate, AllocId , ConstValue , Pointer , Scalar } ;
244+ use rustc:: mir:: interpret:: { truncate, AllocId , Allocation , ConstValue , Pointer , Scalar } ;
245245use rustc:: mir:: Field ;
246246use rustc:: util:: captures:: Captures ;
247247use rustc:: util:: common:: ErrorReported ;
@@ -252,6 +252,7 @@ use syntax_pos::{Span, DUMMY_SP};
252252use arena:: TypedArena ;
253253
254254use smallvec:: { smallvec, SmallVec } ;
255+ use std:: borrow:: Cow ;
255256use std:: cmp:: { self , max, min, Ordering } ;
256257use std:: convert:: TryInto ;
257258use std:: fmt;
@@ -260,11 +261,12 @@ use std::ops::RangeInclusive;
260261use std:: u128;
261262
262263pub fn expand_pattern < ' a , ' tcx > ( cx : & MatchCheckCtxt < ' a , ' tcx > , pat : Pat < ' tcx > ) -> Pat < ' tcx > {
263- LiteralExpander { tcx : cx. tcx } . fold_pattern ( & pat)
264+ LiteralExpander { tcx : cx. tcx , param_env : cx . param_env } . fold_pattern ( & pat)
264265}
265266
266267struct LiteralExpander < ' tcx > {
267268 tcx : TyCtxt < ' tcx > ,
269+ param_env : ty:: ParamEnv < ' tcx > ,
268270}
269271
270272impl LiteralExpander < ' tcx > {
@@ -284,9 +286,23 @@ impl LiteralExpander<'tcx> {
284286 debug ! ( "fold_const_value_deref {:?} {:?} {:?}" , val, rty, crty) ;
285287 match ( val, & crty. kind , & rty. kind ) {
286288 // the easy case, deref a reference
287- ( ConstValue :: Scalar ( Scalar :: Ptr ( p) ) , x, y) if x == y => {
288- let alloc = self . tcx . alloc_map . lock ( ) . unwrap_memory ( p. alloc_id ) ;
289- ConstValue :: ByRef { alloc, offset : p. offset }
289+ ( ConstValue :: Scalar ( p) , x, y) if x == y => {
290+ match p {
291+ Scalar :: Ptr ( p) => {
292+ let alloc = self . tcx . alloc_map . lock ( ) . unwrap_memory ( p. alloc_id ) ;
293+ ConstValue :: ByRef { alloc, offset : p. offset }
294+ }
295+ Scalar :: Raw { .. } => {
296+ let layout = self . tcx . layout_of ( self . param_env . and ( rty) ) . unwrap ( ) ;
297+ if layout. is_zst ( ) {
298+ // Deref of a reference to a ZST is a nop.
299+ ConstValue :: Scalar ( Scalar :: zst ( ) )
300+ } else {
301+ // FIXME(oli-obk): this is reachable for `const FOO: &&&u32 = &&&42;`
302+ bug ! ( "cannot deref {:#?}, {} -> {}" , val, crty, rty) ;
303+ }
304+ }
305+ }
290306 }
291307 // unsize array to slice if pattern is array but match value or other patterns are slice
292308 ( ConstValue :: Scalar ( Scalar :: Ptr ( p) ) , ty:: Array ( t, n) , ty:: Slice ( u) ) => {
@@ -2348,16 +2364,28 @@ fn specialize_one_pattern<'p, 'tcx>(
23482364 // just integers. The only time they should be pointing to memory
23492365 // is when they are subslices of nonzero slices.
23502366 let ( alloc, offset, n, ty) = match value. ty . kind {
2351- ty:: Array ( t, n) => match value. val {
2352- ty:: ConstKind :: Value ( ConstValue :: ByRef { offset, alloc, .. } ) => {
2353- ( alloc, offset, n. eval_usize ( cx. tcx , cx. param_env ) , t)
2367+ ty:: Array ( t, n) => {
2368+ let n = n. eval_usize ( cx. tcx , cx. param_env ) ;
2369+ match value. val {
2370+ ty:: ConstKind :: Value ( ConstValue :: ByRef { offset, alloc, .. } ) => {
2371+ ( Cow :: Borrowed ( alloc) , offset, n, t)
2372+ }
2373+ ty:: ConstKind :: Value ( ConstValue :: Scalar ( Scalar :: Raw { data, .. } ) )
2374+ if n == 0 =>
2375+ {
2376+ let align = Align :: from_bytes ( data as u64 ) . unwrap ( ) ;
2377+ // empty array
2378+ ( Cow :: Owned ( Allocation :: zst ( align) ) , Size :: ZERO , 0 , t)
2379+ }
2380+ _ => span_bug ! ( pat. span, "array pattern is {:?}" , value, ) ,
23542381 }
2355- _ => span_bug ! ( pat. span, "array pattern is {:?}" , value, ) ,
2356- } ,
2382+ }
23572383 ty:: Slice ( t) => {
23582384 match value. val {
23592385 ty:: ConstKind :: Value ( ConstValue :: Slice { data, start, end } ) => {
2360- ( data, Size :: from_bytes ( start as u64 ) , ( end - start) as u64 , t)
2386+ let offset = Size :: from_bytes ( start as u64 ) ;
2387+ let n = ( end - start) as u64 ;
2388+ ( Cow :: Borrowed ( data) , offset, n, t)
23612389 }
23622390 ty:: ConstKind :: Value ( ConstValue :: ByRef { .. } ) => {
23632391 // FIXME(oli-obk): implement `deref` for `ConstValue`
0 commit comments