diff options
Diffstat (limited to 'compiler/rustc_infer/src/infer/freshen.rs')
-rw-r--r-- | compiler/rustc_infer/src/infer/freshen.rs | 150 |
1 files changed, 70 insertions, 80 deletions
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 8f53b1ccd..f09f93abf 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -34,7 +34,7 @@ use super::InferCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_middle::infer::unify_key::ToType; use rustc_middle::ty::fold::TypeFolder; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitableExt}; use std::collections::hash_map::Entry; pub struct TypeFreshener<'a, 'tcx> { @@ -58,14 +58,9 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { } } - fn freshen_ty<F>( - &mut self, - opt_ty: Option<Ty<'tcx>>, - key: ty::InferTy, - freshener: F, - ) -> Ty<'tcx> + fn freshen_ty<F>(&mut self, opt_ty: Option<Ty<'tcx>>, key: ty::InferTy, mk_fresh: F) -> Ty<'tcx> where - F: FnOnce(u32) -> ty::InferTy, + F: FnOnce(u32) -> Ty<'tcx>, { if let Some(ty) = opt_ty { return ty.fold_with(self); @@ -76,7 +71,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { Entry::Vacant(entry) => { let index = self.ty_freshen_count; self.ty_freshen_count += 1; - let t = self.infcx.tcx.mk_ty_infer(freshener(index)); + let t = mk_fresh(index); entry.insert(t); t } @@ -110,8 +105,8 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { } } -impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { +impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> { + fn interner(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -126,92 +121,36 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { | ty::ReFree(_) | ty::ReVar(_) | ty::RePlaceholder(..) + | ty::ReError(_) | ty::ReErased => { // replace all free regions with 'erased - self.tcx().lifetimes.re_erased + self.interner().lifetimes.re_erased } ty::ReStatic => { if self.keep_static { r } else { - self.tcx().lifetimes.re_erased + self.interner().lifetimes.re_erased } } } } + #[inline] fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { if !t.needs_infer() && !t.has_erasable_regions() { - return t; - } + t + } else { + match *t.kind() { + ty::Infer(v) => self.fold_infer_ty(v).unwrap_or(t), - let tcx = self.infcx.tcx; + // This code is hot enough that a non-debug assertion here makes a noticeable + // difference on benchmarks like `wg-grammar`. + #[cfg(debug_assertions)] + ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t), - match *t.kind() { - ty::Infer(ty::TyVar(v)) => { - let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); - self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy) + _ => t.super_fold_with(self), } - - ty::Infer(ty::IntVar(v)) => self.freshen_ty( - self.infcx - .inner - .borrow_mut() - .int_unification_table() - .probe_value(v) - .map(|v| v.to_type(tcx)), - ty::IntVar(v), - ty::FreshIntTy, - ), - - ty::Infer(ty::FloatVar(v)) => self.freshen_ty( - self.infcx - .inner - .borrow_mut() - .float_unification_table() - .probe_value(v) - .map(|v| v.to_type(tcx)), - ty::FloatVar(v), - ty::FreshFloatTy, - ), - - ty::Infer(ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct)) => { - if ct >= self.ty_freshen_count { - bug!( - "Encountered a freshend type with id {} \ - but our counter is only at {}", - ct, - self.ty_freshen_count - ); - } - t - } - - ty::Generator(..) - | ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::Adt(..) - | ty::Str - | ty::Error(_) - | ty::Array(..) - | ty::Slice(..) - | ty::RawPtr(..) - | ty::Ref(..) - | ty::FnDef(..) - | ty::FnPtr(_) - | ty::Dynamic(..) - | ty::Never - | ty::Tuple(..) - | ty::Alias(..) - | ty::Foreign(..) - | ty::Param(..) - | ty::Closure(..) - | ty::GeneratorWitness(..) => t.super_fold_with(self), - - ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t), } } @@ -252,3 +191,54 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { } } } + +impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { + // This is separate from `fold_ty` to keep that method small and inlinable. + #[inline(never)] + fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option<Ty<'tcx>> { + match v { + ty::TyVar(v) => { + let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); + Some(self.freshen_ty(opt_ty, ty::TyVar(v), |n| self.infcx.tcx.mk_fresh_ty(n))) + } + + ty::IntVar(v) => Some( + self.freshen_ty( + self.infcx + .inner + .borrow_mut() + .int_unification_table() + .probe_value(v) + .map(|v| v.to_type(self.infcx.tcx)), + ty::IntVar(v), + |n| self.infcx.tcx.mk_fresh_int_ty(n), + ), + ), + + ty::FloatVar(v) => Some( + self.freshen_ty( + self.infcx + .inner + .borrow_mut() + .float_unification_table() + .probe_value(v) + .map(|v| v.to_type(self.infcx.tcx)), + ty::FloatVar(v), + |n| self.infcx.tcx.mk_fresh_float_ty(n), + ), + ), + + ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct) => { + if ct >= self.ty_freshen_count { + bug!( + "Encountered a freshend type with id {} \ + but our counter is only at {}", + ct, + self.ty_freshen_count + ); + } + None + } + } + } +} |