Skip to content

Commit 1ebc858

Browse files
varkoryodaldevoid
andcommitted
Add const kind and UnpackedKind::Const
Co-Authored-By: Gabriel Smith <[email protected]>
1 parent 691d054 commit 1ebc858

File tree

1 file changed

+110
-6
lines changed

1 file changed

+110
-6
lines changed

src/librustc/ty/subst.rs

Lines changed: 110 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
use crate::hir::def_id::DefId;
44
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};
66
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
7+
use crate::mir::interpret::ConstValue;
78

89
use serialize::{self, Encodable, Encoder, Decodable, Decoder};
910
use syntax_pos::{Span, DUMMY_SP};
@@ -17,24 +18,26 @@ use std::mem;
1718
use std::num::NonZeroUsize;
1819

1920
/// 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).
2122
/// To reduce memory usage, a `Kind` is a interned pointer,
2223
/// 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.
2425
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
2526
pub struct Kind<'tcx> {
2627
ptr: NonZeroUsize,
27-
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>)>
28+
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, &'tcx ty::LazyConst<'tcx>)>
2829
}
2930

3031
const TAG_MASK: usize = 0b11;
3132
const TYPE_TAG: usize = 0b00;
3233
const REGION_TAG: usize = 0b01;
34+
const CONST_TAG: usize = 0b10;
3335

3436
#[derive(Debug, RustcEncodable, RustcDecodable, PartialEq, Eq, PartialOrd, Ord)]
3537
pub enum UnpackedKind<'tcx> {
3638
Lifetime(ty::Region<'tcx>),
3739
Type(Ty<'tcx>),
40+
Const(&'tcx ty::LazyConst<'tcx>),
3841
}
3942

4043
impl<'tcx> UnpackedKind<'tcx> {
@@ -50,6 +53,11 @@ impl<'tcx> UnpackedKind<'tcx> {
5053
assert_eq!(mem::align_of_val(ty) & TAG_MASK, 0);
5154
(TYPE_TAG, ty as *const _ as usize)
5255
}
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+
}
5361
};
5462

5563
Kind {
@@ -85,6 +93,12 @@ impl<'tcx> From<Ty<'tcx>> for Kind<'tcx> {
8593
}
8694
}
8795

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+
88102
impl<'tcx> Kind<'tcx> {
89103
#[inline]
90104
pub fn unpack(self) -> UnpackedKind<'tcx> {
@@ -93,6 +107,7 @@ impl<'tcx> Kind<'tcx> {
93107
match ptr & TAG_MASK {
94108
REGION_TAG => UnpackedKind::Lifetime(&*((ptr & !TAG_MASK) as *const _)),
95109
TYPE_TAG => UnpackedKind::Type(&*((ptr & !TAG_MASK) as *const _)),
110+
CONST_TAG => UnpackedKind::Const(&*((ptr & !TAG_MASK) as *const _)),
96111
_ => intrinsics::unreachable()
97112
}
98113
}
@@ -104,6 +119,7 @@ impl<'tcx> fmt::Debug for Kind<'tcx> {
104119
match self.unpack() {
105120
UnpackedKind::Lifetime(lt) => write!(f, "{:?}", lt),
106121
UnpackedKind::Type(ty) => write!(f, "{:?}", ty),
122+
UnpackedKind::Const(ct) => write!(f, "{:?}", ct),
107123
}
108124
}
109125
}
@@ -113,6 +129,7 @@ impl<'tcx> fmt::Display for Kind<'tcx> {
113129
match self.unpack() {
114130
UnpackedKind::Lifetime(lt) => write!(f, "{}", lt),
115131
UnpackedKind::Type(ty) => write!(f, "{}", ty),
132+
UnpackedKind::Const(ct) => write!(f, "{}", ct),
116133
}
117134
}
118135
}
@@ -122,8 +139,9 @@ impl<'a, 'tcx> Lift<'tcx> for Kind<'a> {
122139

123140
fn lift_to_tcx<'cx, 'gcx>(&self, tcx: TyCtxt<'cx, 'gcx, 'tcx>) -> Option<Self::Lifted> {
124141
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()),
127145
}
128146
}
129147
}
@@ -133,13 +151,15 @@ impl<'tcx> TypeFoldable<'tcx> for Kind<'tcx> {
133151
match self.unpack() {
134152
UnpackedKind::Lifetime(lt) => lt.fold_with(folder).into(),
135153
UnpackedKind::Type(ty) => ty.fold_with(folder).into(),
154+
UnpackedKind::Const(ct) => ct.fold_with(folder).into(),
136155
}
137156
}
138157

139158
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
140159
match self.unpack() {
141160
UnpackedKind::Lifetime(lt) => lt.visit_with(visitor),
142161
UnpackedKind::Type(ty) => ty.visit_with(visitor),
162+
UnpackedKind::Const(ct) => ct.visit_with(visitor),
143163
}
144164
}
145165
}
@@ -195,6 +215,15 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
195215
ty::BoundRegion::BrNamed(param.def_id, param.name)
196216
)).into()
197217
}
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+
}
198227
}
199228
})
200229
}
@@ -283,6 +312,29 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
283312
})
284313
}
285314

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+
286338
#[inline]
287339
pub fn type_at(&self, i: usize) -> Ty<'tcx> {
288340
if let UnpackedKind::Type(ty) = self[i].unpack() {
@@ -301,6 +353,15 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
301353
}
302354
}
303355

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+
304365
#[inline]
305366
pub fn type_for_def(&self, def: &ty::GenericParamDef) -> Kind<'tcx> {
306367
self.type_at(def.index as usize).into()
@@ -469,6 +530,21 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> {
469530

470531
return t1;
471532
}
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+
}
472548
}
473549

474550
impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
@@ -494,6 +570,34 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
494570
self.shift_vars_through_binders(ty)
495571
}
496572

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+
497601
/// It is sometimes necessary to adjust the De Bruijn indices during substitution. This occurs
498602
/// when we are substituting a type with escaping bound vars into a context where we have
499603
/// passed through binders. That's quite a mouthful. Let's see an example:

0 commit comments

Comments
 (0)