@@ -178,11 +178,11 @@ use super::{PatternFoldable, PatternFolder, compare_const_vals};
178
178
179
179
use rustc:: hir:: def_id:: DefId ;
180
180
use rustc:: hir:: RangeEnd ;
181
- use rustc:: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
182
- use rustc:: ty:: layout:: { Integer , IntegerExt , VariantIdx } ;
181
+ use rustc:: ty:: { self , Ty , TyCtxt , TypeFoldable , Const } ;
182
+ use rustc:: ty:: layout:: { Integer , IntegerExt , VariantIdx , Size } ;
183
183
184
184
use rustc:: mir:: Field ;
185
- use rustc:: mir:: interpret:: ConstValue ;
185
+ use rustc:: mir:: interpret:: { ConstValue , Pointer , Scalar } ;
186
186
use rustc:: util:: common:: ErrorReported ;
187
187
188
188
use syntax:: attr:: { SignedInt , UnsignedInt } ;
@@ -200,22 +200,66 @@ use std::u128;
200
200
pub fn expand_pattern < ' a , ' tcx > ( cx : & MatchCheckCtxt < ' a , ' tcx > , pat : Pattern < ' tcx > )
201
201
-> & ' a Pattern < ' tcx >
202
202
{
203
- cx. pattern_arena . alloc ( LiteralExpander . fold_pattern ( & pat) )
203
+ cx. pattern_arena . alloc ( LiteralExpander { tcx : cx . tcx } . fold_pattern ( & pat) )
204
204
}
205
205
206
- struct LiteralExpander ;
207
- impl < ' tcx > PatternFolder < ' tcx > for LiteralExpander {
206
+ struct LiteralExpander < ' a , ' tcx > {
207
+ tcx : TyCtxt < ' a , ' tcx , ' tcx >
208
+ }
209
+
210
+ impl < ' a , ' tcx > LiteralExpander < ' a , ' tcx > {
211
+ /// Derefs `val` and potentially unsizes the value if `crty` is an array and `rty` a slice
212
+ fn fold_const_value_deref (
213
+ & mut self ,
214
+ val : ConstValue < ' tcx > ,
215
+ rty : Ty < ' tcx > ,
216
+ crty : Ty < ' tcx > ,
217
+ ) -> ConstValue < ' tcx > {
218
+ match ( val, & crty. sty , & rty. sty ) {
219
+ // the easy case, deref a reference
220
+ ( ConstValue :: Scalar ( Scalar :: Ptr ( p) ) , x, y) if x == y => ConstValue :: ByRef (
221
+ p. alloc_id ,
222
+ self . tcx . alloc_map . lock ( ) . unwrap_memory ( p. alloc_id ) ,
223
+ p. offset ,
224
+ ) ,
225
+ // unsize array to slice if pattern is array but match value or other patterns are slice
226
+ ( ConstValue :: Scalar ( Scalar :: Ptr ( p) ) , ty:: Array ( t, n) , ty:: Slice ( u) ) => {
227
+ assert_eq ! ( t, u) ;
228
+ ConstValue :: ScalarPair (
229
+ Scalar :: Ptr ( p) ,
230
+ n. val . try_to_scalar ( ) . unwrap ( ) ,
231
+ )
232
+ } ,
233
+ // fat pointers stay the same
234
+ ( ConstValue :: ScalarPair ( ..) , _, _) => val,
235
+ // FIXME(oli-obk): this is reachable for `const FOO: &&&u32 = &&&42;` being used
236
+ _ => bug ! ( "cannot deref {:#?}, {} -> {}" , val, crty, rty) ,
237
+ }
238
+ }
239
+ }
240
+
241
+ impl < ' a , ' tcx > PatternFolder < ' tcx > for LiteralExpander < ' a , ' tcx > {
208
242
fn fold_pattern ( & mut self , pat : & Pattern < ' tcx > ) -> Pattern < ' tcx > {
209
243
match ( & pat. ty . sty , & * pat. kind ) {
210
- ( & ty:: Ref ( _, rty, _) , & PatternKind :: Constant { ref value } ) => {
244
+ (
245
+ & ty:: Ref ( _, rty, _) ,
246
+ & PatternKind :: Constant { value : Const {
247
+ val,
248
+ ty : ty:: TyS { sty : ty:: Ref ( _, crty, _) , .. } ,
249
+ } } ,
250
+ ) => {
211
251
Pattern {
212
252
ty : pat. ty ,
213
253
span : pat. span ,
214
254
kind : box PatternKind :: Deref {
215
255
subpattern : Pattern {
216
256
ty : rty,
217
257
span : pat. span ,
218
- kind : box PatternKind :: Constant { value : value. clone ( ) } ,
258
+ kind : box PatternKind :: Constant { value : Const :: from_const_value (
259
+ self . tcx ,
260
+ self . fold_const_value_deref ( * val, rty, crty) ,
261
+ rty,
262
+ ) } ,
219
263
}
220
264
}
221
265
}
@@ -732,15 +776,16 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
732
776
for row in patterns {
733
777
match * row. kind {
734
778
PatternKind :: Constant { value } => {
735
- if let Some ( ptr) = value. to_ptr ( ) {
736
- let is_array_ptr = value. ty
737
- . builtin_deref ( true )
738
- . and_then ( |t| t. ty . builtin_index ( ) )
739
- . map_or ( false , |t| t == cx. tcx . types . u8 ) ;
740
- if is_array_ptr {
741
- let alloc = cx. tcx . alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) ;
742
- max_fixed_len = cmp:: max ( max_fixed_len, alloc. bytes . len ( ) as u64 ) ;
743
- }
779
+ match ( value. val , & value. ty . sty ) {
780
+ ( _, ty:: Array ( _, n) ) => max_fixed_len = cmp:: max (
781
+ max_fixed_len,
782
+ n. unwrap_usize ( cx. tcx ) ,
783
+ ) ,
784
+ ( ConstValue :: ScalarPair ( _, n) , ty:: Slice ( _) ) => max_fixed_len = cmp:: max (
785
+ max_fixed_len,
786
+ n. to_usize ( & cx. tcx ) . unwrap ( ) ,
787
+ ) ,
788
+ _ => { } ,
744
789
}
745
790
}
746
791
PatternKind :: Slice { ref prefix, slice : None , ref suffix } => {
@@ -1358,18 +1403,44 @@ fn slice_pat_covered_by_constructor<'tcx>(
1358
1403
) -> Result < bool , ErrorReported > {
1359
1404
let data: & [ u8 ] = match * ctor {
1360
1405
ConstantValue ( const_val) => {
1361
- let val = match const_val. val {
1362
- ConstValue :: Unevaluated ( ..) |
1363
- ConstValue :: ByRef ( ..) => bug ! ( "unexpected ConstValue: {:?}" , const_val) ,
1364
- ConstValue :: Scalar ( val) | ConstValue :: ScalarPair ( val, _) => val,
1365
- } ;
1366
- if let Ok ( ptr) = val. to_ptr ( ) {
1367
- tcx. alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) . bytes . as_ref ( )
1368
- } else {
1369
- bug ! ( "unexpected non-ptr ConstantValue" )
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
+ ) ,
1370
1438
}
1371
1439
}
1372
- _ => bug ! ( )
1440
+ _ => bug ! (
1441
+ "slice_pat_covered_by_constructor not ConstValue: {:#?}, {:#?}, {:#?}, {:#?}" ,
1442
+ ctor, prefix, slice, suffix,
1443
+ ) ,
1373
1444
} ;
1374
1445
1375
1446
let pat_len = prefix. len ( ) + suffix. len ( ) ;
@@ -1675,22 +1746,23 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
1675
1746
// necessarily point to memory, they are usually just integers. The only time
1676
1747
// they should be pointing to memory is when they are subslices of nonzero
1677
1748
// slices
1678
- let ( opt_ptr, n, ty) = match value. ty . builtin_deref ( false ) . unwrap ( ) . ty . sty {
1679
- ty:: TyKind :: Array ( t, n) => ( value. to_ptr ( ) , n. unwrap_usize ( cx. tcx ) , t) ,
1680
- ty:: TyKind :: Slice ( t) => {
1681
- match value. val {
1682
- ConstValue :: ScalarPair ( ptr, n) => (
1683
- ptr. to_ptr ( ) . ok ( ) ,
1684
- n. to_bits ( cx. tcx . data_layout . pointer_size ) . unwrap ( ) as u64 ,
1685
- t,
1686
- ) ,
1687
- _ => span_bug ! (
1688
- pat. span,
1689
- "slice pattern constant must be scalar pair but is {:?}" ,
1690
- value,
1691
- ) ,
1692
- }
1693
- } ,
1749
+ let ( opt_ptr, n, ty) = match ( value. val , & value. ty . sty ) {
1750
+ ( ConstValue :: ByRef ( id, alloc, offset) , ty:: TyKind :: Array ( t, n) ) => (
1751
+ Some ( (
1752
+ Pointer :: new ( id, offset) ,
1753
+ alloc,
1754
+ ) ) ,
1755
+ n. unwrap_usize ( cx. tcx ) ,
1756
+ t,
1757
+ ) ,
1758
+ ( ConstValue :: ScalarPair ( ptr, n) , ty:: TyKind :: Slice ( t) ) => (
1759
+ ptr. to_ptr ( ) . ok ( ) . map ( |ptr| (
1760
+ ptr,
1761
+ cx. tcx . alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) ,
1762
+ ) ) ,
1763
+ n. to_bits ( cx. tcx . data_layout . pointer_size ) . unwrap ( ) as u64 ,
1764
+ t,
1765
+ ) ,
1694
1766
_ => span_bug ! (
1695
1767
pat. span,
1696
1768
"unexpected const-val {:?} with ctor {:?}" ,
@@ -1702,8 +1774,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
1702
1774
// convert a constant slice/array pattern to a list of patterns.
1703
1775
match ( n, opt_ptr) {
1704
1776
( 0 , _) => Some ( SmallVec :: new ( ) ) ,
1705
- ( _, Some ( ptr) ) => {
1706
- let alloc = cx. tcx . alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) ;
1777
+ ( _, Some ( ( ptr, alloc) ) ) => {
1707
1778
let layout = cx. tcx . layout_of ( cx. param_env . and ( ty) ) . ok ( ) ?;
1708
1779
( 0 ..n) . map ( |i| {
1709
1780
let ptr = ptr. offset ( layout. size * i, & cx. tcx ) . ok ( ) ?;
0 commit comments