Skip to content

Commit

Permalink
impl fold_const for TypeFreshener
Browse files Browse the repository at this point in the history
Signed-off-by: Gabriel Smith <ga29smith@gmail.com>
  • Loading branch information
yodaldevoid authored and varkor committed May 1, 2019
1 parent e965b75 commit c13aa09
Showing 1 changed file with 92 additions and 22 deletions.
114 changes: 92 additions & 22 deletions src/librustc/infer/freshen.rs
Expand Up @@ -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;
Expand All @@ -42,42 +43,74 @@ 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> {
pub fn new(infcx: &'a InferCtxt<'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> {
Expand Down Expand Up @@ -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)),
Expand All @@ -140,22 +173,22 @@ 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)),
ty::FloatVar(v),
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
}
Expand Down Expand Up @@ -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)
}
}

0 comments on commit c13aa09

Please sign in to comment.