impl fold_const for TypeFreshener
Signed-off-by: Gabriel Smith <ga29smith@gmail.com>
This commit is contained in:
parent
e965b75603
commit
c13aa09d49
1 changed files with 92 additions and 22 deletions
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue