@@ -178,11 +178,11 @@ use super::{PatternFoldable, PatternFolder, compare_const_vals};
178178
179179use rustc:: hir:: def_id:: DefId ;
180180use 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 } ;
183183
184184use rustc:: mir:: Field ;
185- use rustc:: mir:: interpret:: ConstValue ;
185+ use rustc:: mir:: interpret:: { ConstValue , Pointer , Scalar } ;
186186use rustc:: util:: common:: ErrorReported ;
187187
188188use syntax:: attr:: { SignedInt , UnsignedInt } ;
@@ -200,22 +200,66 @@ use std::u128;
200200pub fn expand_pattern < ' a , ' tcx > ( cx : & MatchCheckCtxt < ' a , ' tcx > , pat : Pattern < ' tcx > )
201201 -> & ' a Pattern < ' tcx >
202202{
203- cx. pattern_arena . alloc ( LiteralExpander . fold_pattern ( & pat) )
203+ cx. pattern_arena . alloc ( LiteralExpander { tcx : cx . tcx } . fold_pattern ( & pat) )
204204}
205205
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 > {
208242 fn fold_pattern ( & mut self , pat : & Pattern < ' tcx > ) -> Pattern < ' tcx > {
209243 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+ ) => {
211251 Pattern {
212252 ty : pat. ty ,
213253 span : pat. span ,
214254 kind : box PatternKind :: Deref {
215255 subpattern : Pattern {
216256 ty : rty,
217257 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+ ) } ,
219263 }
220264 }
221265 }
@@ -732,15 +776,16 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
732776 for row in patterns {
733777 match * row. kind {
734778 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+ _ => { } ,
744789 }
745790 }
746791 PatternKind :: Slice { ref prefix, slice : None , ref suffix } => {
@@ -1358,18 +1403,44 @@ fn slice_pat_covered_by_constructor<'tcx>(
13581403) -> Result < bool , ErrorReported > {
13591404 let data: & [ u8 ] = match * ctor {
13601405 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+ ) ,
13701438 }
13711439 }
1372- _ => bug ! ( )
1440+ _ => bug ! (
1441+ "slice_pat_covered_by_constructor not ConstValue: {:#?}, {:#?}, {:#?}, {:#?}" ,
1442+ ctor, prefix, slice, suffix,
1443+ ) ,
13731444 } ;
13741445
13751446 let pat_len = prefix. len ( ) + suffix. len ( ) ;
@@ -1675,22 +1746,23 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
16751746 // necessarily point to memory, they are usually just integers. The only time
16761747 // they should be pointing to memory is when they are subslices of nonzero
16771748 // 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+ ) ,
16941766 _ => span_bug ! (
16951767 pat. span,
16961768 "unexpected const-val {:?} with ctor {:?}" ,
@@ -1702,8 +1774,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
17021774 // convert a constant slice/array pattern to a list of patterns.
17031775 match ( n, opt_ptr) {
17041776 ( 0 , _) => Some ( SmallVec :: new ( ) ) ,
1705- ( _, Some ( ptr) ) => {
1706- let alloc = cx. tcx . alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) ;
1777+ ( _, Some ( ( ptr, alloc) ) ) => {
17071778 let layout = cx. tcx . layout_of ( cx. param_env . and ( ty) ) . ok ( ) ?;
17081779 ( 0 ..n) . map ( |i| {
17091780 let ptr = ptr. offset ( layout. size * i, & cx. tcx ) . ok ( ) ?;
0 commit comments