From c13aa09d498eb02c271e89da266c40686524a7dc Mon Sep 17 00:00:00 2001 From: Gabriel Smith Date: Thu, 28 Feb 2019 23:05:47 -0500 Subject: [PATCH] impl fold_const for TypeFreshener Signed-off-by: Gabriel Smith --- src/librustc/infer/freshen.rs | 114 +++++++++++++++++++++++++++------- 1 file changed, 92 insertions(+), 22 deletions(-) diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index a45f01043f33..b43f78efffb6 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -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_freshen_count: u32, + const_freshen_count: u32, + ty_freshen_map: FxHashMap>, + const_freshen_map: FxHashMap, &'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(&mut self, - opt_ty: Option>, - key: ty::InferTy, - freshener: F) - -> Ty<'tcx> where + fn freshen_ty( + &mut self, + opt_ty: Option>, + 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( + &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) } }