1
Fork 0

impl fold_const for TypeFreshener

Signed-off-by: Gabriel Smith <ga29smith@gmail.com>
This commit is contained in:
Gabriel Smith 2019-02-28 23:05:47 -05:00 committed by varkor
parent e965b75603
commit c13aa09d49

View file

@ -31,6 +31,7 @@
//! variable only once, and it does so as soon as it can, so it is reasonable to ask what the type
//! inferencer knows "so far".
use crate::mir::interpret::ConstValue;
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use crate::ty::fold::TypeFolder;
use crate::util::nodemap::FxHashMap;
@ -42,8 +43,10 @@ use super::unify_key::ToType;
pub struct TypeFreshener<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
freshen_count: u32,
freshen_map: FxHashMap<ty::InferTy, Ty<'tcx>>,
ty_freshen_count: u32,
const_freshen_count: u32,
ty_freshen_map: FxHashMap<ty::InferTy, Ty<'tcx>>,
const_freshen_map: FxHashMap<ty::InferConst<'tcx>, &'tcx ty::LazyConst<'tcx>>,
}
impl<'a, 'gcx, 'tcx> TypeFreshener<'a, 'gcx, 'tcx> {
@ -51,33 +54,63 @@ impl<'a, 'gcx, 'tcx> TypeFreshener<'a, 'gcx, 'tcx> {
-> TypeFreshener<'a, 'gcx, 'tcx> {
TypeFreshener {
infcx,
freshen_count: 0,
freshen_map: Default::default(),
ty_freshen_count: 0,
const_freshen_count: 0,
ty_freshen_map: Default::default(),
const_freshen_map: Default::default(),
}
}
fn freshen<F>(&mut self,
opt_ty: Option<Ty<'tcx>>,
key: ty::InferTy,
freshener: F)
-> Ty<'tcx> where
fn freshen_ty<F>(
&mut self,
opt_ty: Option<Ty<'tcx>>,
key: ty::InferTy,
freshener: F,
) -> Ty<'tcx>
where
F: FnOnce(u32) -> ty::InferTy,
{
if let Some(ty) = opt_ty {
return ty.fold_with(self);
}
match self.freshen_map.entry(key) {
match self.ty_freshen_map.entry(key) {
Entry::Occupied(entry) => *entry.get(),
Entry::Vacant(entry) => {
let index = self.freshen_count;
self.freshen_count += 1;
let index = self.ty_freshen_count;
self.ty_freshen_count += 1;
let t = self.infcx.tcx.mk_ty_infer(freshener(index));
entry.insert(t);
t
}
}
}
fn freshen_const<F>(
&mut self,
opt_ct: Option<&'tcx ty::LazyConst<'tcx>>,
key: ty::InferConst<'tcx>,
freshener: F,
ty: Ty<'tcx>,
) -> &'tcx ty::LazyConst<'tcx>
where
F: FnOnce(u32) -> ty::InferConst<'tcx>,
{
if let Some(ct) = opt_ct {
return ct.fold_with(self);
}
match self.const_freshen_map.entry(key) {
Entry::Occupied(entry) => *entry.get(),
Entry::Vacant(entry) => {
let index = self.const_freshen_count;
self.const_freshen_count += 1;
let ct = self.infcx.tcx.mk_const_infer(freshener(index), ty);
entry.insert(ct);
ct
}
}
}
}
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
@ -124,14 +157,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
match t.sty {
ty::Infer(ty::TyVar(v)) => {
let opt_ty = self.infcx.type_variables.borrow_mut().probe(v).known();
self.freshen(
self.freshen_ty(
opt_ty,
ty::TyVar(v),
ty::FreshTy)
}
ty::Infer(ty::IntVar(v)) => {
self.freshen(
self.freshen_ty(
self.infcx.int_unification_table.borrow_mut()
.probe_value(v)
.map(|v| v.to_type(tcx)),
@ -140,7 +173,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
}
ty::Infer(ty::FloatVar(v)) => {
self.freshen(
self.freshen_ty(
self.infcx.float_unification_table.borrow_mut()
.probe_value(v)
.map(|v| v.to_type(tcx)),
@ -148,14 +181,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::FreshFloatTy)
}
ty::Infer(ty::FreshTy(c)) |
ty::Infer(ty::FreshIntTy(c)) |
ty::Infer(ty::FreshFloatTy(c)) => {
if c >= self.freshen_count {
ty::Infer(ty::FreshTy(ct)) |
ty::Infer(ty::FreshIntTy(ct)) |
ty::Infer(ty::FreshFloatTy(ct)) => {
if ct >= self.ty_freshen_count {
bug!("Encountered a freshend type with id {} \
but our counter is only at {}",
c,
self.freshen_count);
ct,
self.ty_freshen_count);
}
t
}
@ -194,6 +227,43 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
}
fn fold_const(&mut self, ct: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
ct // FIXME(const_generics)
if let ty::LazyConst::Evaluated(ty::Const{ val, ty }) = ct {
match val {
ConstValue::Infer(ty::InferConst::Var(v)) => {
let opt_ct = self.infcx.const_unification_table
.borrow_mut()
.probe(*v)
.known();
return self.freshen_const(
opt_ct,
ty::InferConst::Var(*v),
ty::InferConst::Fresh,
ty,
);
}
ConstValue::Infer(ty::InferConst::Fresh(i)) => {
if *i >= self.const_freshen_count {
bug!(
"Encountered a freshend const with id {} \
but our counter is only at {}",
i,
self.const_freshen_count,
);
}
return ct;
}
ConstValue::Infer(ty::InferConst::Canonical(..)) => {
bug!("unexpected const {:?}", ct)
}
ConstValue::Param(_) |
ConstValue::Scalar(_) |
ConstValue::Slice(..) |
ConstValue::ByRef(..) => {}
}
}
ct.super_fold_with(self)
}
}