@@ -237,11 +237,11 @@ use super::{FieldPat, Pat, PatKind, PatRange};
237
237
238
238
use rustc:: hir:: def_id:: DefId ;
239
239
use rustc:: hir:: { HirId , RangeEnd } ;
240
- use rustc:: ty:: layout:: { Integer , IntegerExt , Size , VariantIdx } ;
240
+ use rustc:: ty:: layout:: { Integer , IntegerExt , Size , VariantIdx , Align } ;
241
241
use rustc:: ty:: { self , Const , Ty , TyCtxt , TypeFoldable , VariantDef } ;
242
242
243
243
use rustc:: lint;
244
- use rustc:: mir:: interpret:: { truncate, AllocId , ConstValue , Pointer , Scalar } ;
244
+ use rustc:: mir:: interpret:: { truncate, AllocId , ConstValue , Pointer , Scalar , Allocation } ;
245
245
use rustc:: mir:: Field ;
246
246
use rustc:: util:: captures:: Captures ;
247
247
use rustc:: util:: common:: ErrorReported ;
@@ -258,13 +258,15 @@ use std::fmt;
258
258
use std:: iter:: { FromIterator , IntoIterator } ;
259
259
use std:: ops:: RangeInclusive ;
260
260
use std:: u128;
261
+ use std:: borrow:: Cow ;
261
262
262
263
pub 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)
264
265
}
265
266
266
267
struct LiteralExpander < ' tcx > {
267
268
tcx : TyCtxt < ' tcx > ,
269
+ param_env : ty:: ParamEnv < ' tcx > ,
268
270
}
269
271
270
272
impl LiteralExpander < ' tcx > {
@@ -284,9 +286,23 @@ impl LiteralExpander<'tcx> {
284
286
debug ! ( "fold_const_value_deref {:?} {:?} {:?}" , val, rty, crty) ;
285
287
match ( val, & crty. kind , & rty. kind ) {
286
288
// 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
+ }
290
306
}
291
307
// unsize array to slice if pattern is array but match value or other patterns are slice
292
308
( ConstValue :: Scalar ( Scalar :: Ptr ( p) ) , ty:: Array ( t, n) , ty:: Slice ( u) ) => {
@@ -2347,16 +2363,27 @@ fn specialize_one_pattern<'p, 'tcx>(
2347
2363
// just integers. The only time they should be pointing to memory
2348
2364
// is when they are subslices of nonzero slices.
2349
2365
let ( alloc, offset, n, ty) = match value. ty . kind {
2350
- ty:: Array ( t, n) => match value. val {
2351
- ty:: ConstKind :: Value ( ConstValue :: ByRef { offset, alloc, .. } ) => {
2352
- ( alloc, offset, n. eval_usize ( cx. tcx , cx. param_env ) , t)
2366
+ ty:: Array ( t, n) => {
2367
+ let n = n. eval_usize ( cx. tcx , cx. param_env ) ;
2368
+ match value. val {
2369
+ ty:: ConstKind :: Value ( ConstValue :: ByRef { offset, alloc, .. } ) => {
2370
+ ( Cow :: Borrowed ( alloc) , offset, n, t)
2371
+ }
2372
+ ty:: ConstKind :: Value ( ConstValue :: Scalar ( Scalar :: Raw { data, .. } ) )
2373
+ if n == 0 => {
2374
+ let align = Align :: from_bytes ( data as u64 ) . unwrap ( ) ;
2375
+ // empty array
2376
+ ( Cow :: Owned ( Allocation :: zst ( align) ) , Size :: ZERO , 0 , t)
2377
+ }
2378
+ _ => span_bug ! ( pat. span, "array pattern is {:?}" , value, ) ,
2353
2379
}
2354
- _ => span_bug ! ( pat. span, "array pattern is {:?}" , value, ) ,
2355
2380
} ,
2356
2381
ty:: Slice ( t) => {
2357
2382
match value. val {
2358
2383
ty:: ConstKind :: Value ( ConstValue :: Slice { data, start, end } ) => {
2359
- ( data, Size :: from_bytes ( start as u64 ) , ( end - start) as u64 , t)
2384
+ let offset = Size :: from_bytes ( start as u64 ) ;
2385
+ let n = ( end - start) as u64 ;
2386
+ ( Cow :: Borrowed ( data) , offset, n, t)
2360
2387
}
2361
2388
ty:: ConstKind :: Value ( ConstValue :: ByRef { .. } ) => {
2362
2389
// FIXME(oli-obk): implement `deref` for `ConstValue`
0 commit comments