2
2
3
3
use crate :: hir:: def_id:: DefId ;
4
4
use crate :: infer:: canonical:: Canonical ;
5
- use crate :: ty:: { self , Lift , List , Ty , TyCtxt } ;
5
+ use crate :: ty:: { self , Lift , List , Ty , TyCtxt , InferConst , ParamConst } ;
6
6
use crate :: ty:: fold:: { TypeFoldable , TypeFolder , TypeVisitor } ;
7
+ use crate :: mir:: interpret:: ConstValue ;
7
8
8
9
use serialize:: { self , Encodable , Encoder , Decodable , Decoder } ;
9
10
use syntax_pos:: { Span , DUMMY_SP } ;
@@ -17,24 +18,26 @@ use std::mem;
17
18
use std:: num:: NonZeroUsize ;
18
19
19
20
/// An entity in the Rust type system, which can be one of
20
- /// several kinds (only types and lifetimes for now ).
21
+ /// several kinds (types, lifetimes, and consts ).
21
22
/// To reduce memory usage, a `Kind` is a interned pointer,
22
23
/// with the lowest 2 bits being reserved for a tag to
23
- /// indicate the type (`Ty` or `Region `) it points to.
24
+ /// indicate the type (`Ty`, `Region`, or `Const `) it points to.
24
25
#[ derive( Copy , Clone , PartialEq , Eq , Hash ) ]
25
26
pub struct Kind < ' tcx > {
26
27
ptr : NonZeroUsize ,
27
- marker : PhantomData < ( Ty < ' tcx > , ty:: Region < ' tcx > ) >
28
+ marker : PhantomData < ( Ty < ' tcx > , ty:: Region < ' tcx > , & ' tcx ty :: LazyConst < ' tcx > ) >
28
29
}
29
30
30
31
const TAG_MASK : usize = 0b11 ;
31
32
const TYPE_TAG : usize = 0b00 ;
32
33
const REGION_TAG : usize = 0b01 ;
34
+ const CONST_TAG : usize = 0b10 ;
33
35
34
36
#[ derive( Debug , RustcEncodable , RustcDecodable , PartialEq , Eq , PartialOrd , Ord ) ]
35
37
pub enum UnpackedKind < ' tcx > {
36
38
Lifetime ( ty:: Region < ' tcx > ) ,
37
39
Type ( Ty < ' tcx > ) ,
40
+ Const ( & ' tcx ty:: LazyConst < ' tcx > ) ,
38
41
}
39
42
40
43
impl < ' tcx > UnpackedKind < ' tcx > {
@@ -50,6 +53,11 @@ impl<'tcx> UnpackedKind<'tcx> {
50
53
assert_eq ! ( mem:: align_of_val( ty) & TAG_MASK , 0 ) ;
51
54
( TYPE_TAG , ty as * const _ as usize )
52
55
}
56
+ UnpackedKind :: Const ( ct) => {
57
+ // Ensure we can use the tag bits.
58
+ assert_eq ! ( mem:: align_of_val( ct) & TAG_MASK , 0 ) ;
59
+ ( CONST_TAG , ct as * const _ as usize )
60
+ }
53
61
} ;
54
62
55
63
Kind {
@@ -85,6 +93,12 @@ impl<'tcx> From<Ty<'tcx>> for Kind<'tcx> {
85
93
}
86
94
}
87
95
96
+ impl < ' tcx > From < & ' tcx ty:: LazyConst < ' tcx > > for Kind < ' tcx > {
97
+ fn from ( c : & ' tcx ty:: LazyConst < ' tcx > ) -> Kind < ' tcx > {
98
+ UnpackedKind :: Const ( c) . pack ( )
99
+ }
100
+ }
101
+
88
102
impl < ' tcx > Kind < ' tcx > {
89
103
#[ inline]
90
104
pub fn unpack ( self ) -> UnpackedKind < ' tcx > {
@@ -93,6 +107,7 @@ impl<'tcx> Kind<'tcx> {
93
107
match ptr & TAG_MASK {
94
108
REGION_TAG => UnpackedKind :: Lifetime ( & * ( ( ptr & !TAG_MASK ) as * const _ ) ) ,
95
109
TYPE_TAG => UnpackedKind :: Type ( & * ( ( ptr & !TAG_MASK ) as * const _ ) ) ,
110
+ CONST_TAG => UnpackedKind :: Const ( & * ( ( ptr & !TAG_MASK ) as * const _ ) ) ,
96
111
_ => intrinsics:: unreachable ( )
97
112
}
98
113
}
@@ -104,6 +119,7 @@ impl<'tcx> fmt::Debug for Kind<'tcx> {
104
119
match self . unpack ( ) {
105
120
UnpackedKind :: Lifetime ( lt) => write ! ( f, "{:?}" , lt) ,
106
121
UnpackedKind :: Type ( ty) => write ! ( f, "{:?}" , ty) ,
122
+ UnpackedKind :: Const ( ct) => write ! ( f, "{:?}" , ct) ,
107
123
}
108
124
}
109
125
}
@@ -113,6 +129,7 @@ impl<'tcx> fmt::Display for Kind<'tcx> {
113
129
match self . unpack ( ) {
114
130
UnpackedKind :: Lifetime ( lt) => write ! ( f, "{}" , lt) ,
115
131
UnpackedKind :: Type ( ty) => write ! ( f, "{}" , ty) ,
132
+ UnpackedKind :: Const ( ct) => write ! ( f, "{}" , ct) ,
116
133
}
117
134
}
118
135
}
@@ -122,8 +139,9 @@ impl<'a, 'tcx> Lift<'tcx> for Kind<'a> {
122
139
123
140
fn lift_to_tcx < ' cx , ' gcx > ( & self , tcx : TyCtxt < ' cx , ' gcx , ' tcx > ) -> Option < Self :: Lifted > {
124
141
match self . unpack ( ) {
125
- UnpackedKind :: Lifetime ( a) => a. lift_to_tcx ( tcx) . map ( |a| a. into ( ) ) ,
126
- UnpackedKind :: Type ( a) => a. lift_to_tcx ( tcx) . map ( |a| a. into ( ) ) ,
142
+ UnpackedKind :: Lifetime ( lt) => lt. lift_to_tcx ( tcx) . map ( |lt| lt. into ( ) ) ,
143
+ UnpackedKind :: Type ( ty) => ty. lift_to_tcx ( tcx) . map ( |ty| ty. into ( ) ) ,
144
+ UnpackedKind :: Const ( ct) => ct. lift_to_tcx ( tcx) . map ( |ct| ct. into ( ) ) ,
127
145
}
128
146
}
129
147
}
@@ -133,13 +151,15 @@ impl<'tcx> TypeFoldable<'tcx> for Kind<'tcx> {
133
151
match self . unpack ( ) {
134
152
UnpackedKind :: Lifetime ( lt) => lt. fold_with ( folder) . into ( ) ,
135
153
UnpackedKind :: Type ( ty) => ty. fold_with ( folder) . into ( ) ,
154
+ UnpackedKind :: Const ( ct) => ct. fold_with ( folder) . into ( ) ,
136
155
}
137
156
}
138
157
139
158
fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
140
159
match self . unpack ( ) {
141
160
UnpackedKind :: Lifetime ( lt) => lt. visit_with ( visitor) ,
142
161
UnpackedKind :: Type ( ty) => ty. visit_with ( visitor) ,
162
+ UnpackedKind :: Const ( ct) => ct. visit_with ( visitor) ,
143
163
}
144
164
}
145
165
}
@@ -195,6 +215,15 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
195
215
ty:: BoundRegion :: BrNamed ( param. def_id , param. name )
196
216
) ) . into ( )
197
217
}
218
+
219
+ ty:: GenericParamDefKind :: Const => {
220
+ tcx. mk_lazy_const ( ty:: LazyConst :: Evaluated ( ty:: Const {
221
+ val : ConstValue :: Infer (
222
+ InferConst :: Canonical ( ty:: INNERMOST , ty:: BoundVar :: from ( param. index ) )
223
+ ) ,
224
+ ty : tcx. type_of ( def_id) ,
225
+ } ) ) . into ( )
226
+ }
198
227
}
199
228
} )
200
229
}
@@ -283,6 +312,29 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
283
312
} )
284
313
}
285
314
315
+ #[ inline]
316
+ pub fn consts ( & ' a self ) -> impl DoubleEndedIterator < Item = & ' tcx ty:: LazyConst < ' tcx > > + ' a {
317
+ self . iter ( ) . filter_map ( |k| {
318
+ if let UnpackedKind :: Const ( ct) = k. unpack ( ) {
319
+ Some ( ct)
320
+ } else {
321
+ None
322
+ }
323
+ } )
324
+ }
325
+
326
+ #[ inline]
327
+ pub fn non_erasable_generics (
328
+ & ' a self
329
+ ) -> impl DoubleEndedIterator < Item = UnpackedKind < ' tcx > > + ' a {
330
+ self . iter ( ) . filter_map ( |k| {
331
+ match k. unpack ( ) {
332
+ UnpackedKind :: Lifetime ( _) => None ,
333
+ generic => Some ( generic) ,
334
+ }
335
+ } )
336
+ }
337
+
286
338
#[ inline]
287
339
pub fn type_at ( & self , i : usize ) -> Ty < ' tcx > {
288
340
if let UnpackedKind :: Type ( ty) = self [ i] . unpack ( ) {
@@ -301,6 +353,15 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
301
353
}
302
354
}
303
355
356
+ #[ inline]
357
+ pub fn const_at ( & self , i : usize ) -> & ' tcx ty:: LazyConst < ' tcx > {
358
+ if let UnpackedKind :: Const ( ct) = self [ i] . unpack ( ) {
359
+ ct
360
+ } else {
361
+ bug ! ( "expected const for param #{} in {:?}" , i, self ) ;
362
+ }
363
+ }
364
+
304
365
#[ inline]
305
366
pub fn type_for_def ( & self , def : & ty:: GenericParamDef ) -> Kind < ' tcx > {
306
367
self . type_at ( def. index as usize ) . into ( )
@@ -469,6 +530,21 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> {
469
530
470
531
return t1;
471
532
}
533
+
534
+ fn fold_const ( & mut self , c : & ' tcx ty:: LazyConst < ' tcx > ) -> & ' tcx ty:: LazyConst < ' tcx > {
535
+ if !c. needs_subst ( ) {
536
+ return c;
537
+ }
538
+
539
+ if let ty:: LazyConst :: Evaluated ( ty:: Const {
540
+ val : ConstValue :: Param ( p) ,
541
+ ..
542
+ } ) = c {
543
+ self . const_for_param ( * p, c)
544
+ } else {
545
+ c. super_fold_with ( self )
546
+ }
547
+ }
472
548
}
473
549
474
550
impl < ' a , ' gcx , ' tcx > SubstFolder < ' a , ' gcx , ' tcx > {
@@ -494,6 +570,34 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
494
570
self . shift_vars_through_binders ( ty)
495
571
}
496
572
573
+ fn const_for_param (
574
+ & self ,
575
+ p : ParamConst ,
576
+ source_cn : & ' tcx ty:: LazyConst < ' tcx >
577
+ ) -> & ' tcx ty:: LazyConst < ' tcx > {
578
+ // Look up the const in the substitutions. It really should be in there.
579
+ let opt_cn = self . substs . get ( p. index as usize ) . map ( |k| k. unpack ( ) ) ;
580
+ let cn = match opt_cn {
581
+ Some ( UnpackedKind :: Const ( cn) ) => cn,
582
+ _ => {
583
+ let span = self . span . unwrap_or ( DUMMY_SP ) ;
584
+ span_bug ! (
585
+ span,
586
+ "Const parameter `{:?}` ({:?}/{}) out of range \
587
+ when substituting (root type={:?}) substs={:?}",
588
+ p,
589
+ source_cn,
590
+ p. index,
591
+ self . root_ty,
592
+ self . substs,
593
+ ) ;
594
+ }
595
+ } ;
596
+
597
+ // FIXME(const_generics): shift const through binders
598
+ cn
599
+ }
600
+
497
601
/// It is sometimes necessary to adjust the De Bruijn indices during substitution. This occurs
498
602
/// when we are substituting a type with escaping bound vars into a context where we have
499
603
/// passed through binders. That's quite a mouthful. Let's see an example:
0 commit comments