1
Fork 0

Create ShallowResolver

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
This commit is contained in:
varkor 2019-04-30 22:27:33 +01:00
parent 1369132afa
commit 541de81f8e
12 changed files with 128 additions and 108 deletions

View file

@ -18,7 +18,7 @@ use crate::mir::interpret::ConstValue;
use crate::session::config::BorrowckMode;
use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine};
use crate::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
use crate::ty::fold::TypeFoldable;
use crate::ty::fold::{TypeFolder, TypeFoldable};
use crate::ty::relate::RelateResult;
use crate::ty::subst::{Kind, InternalSubsts, SubstsRef};
use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt, CtxtInterners, InferConst};
@ -919,17 +919,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
predicate: &ty::PolySubtypePredicate<'tcx>,
) -> Option<InferResult<'tcx, ()>> {
// Subtle: it's ok to skip the binder here and resolve because
// `shallow_resolve_type` just ignores anything that is not a type
// `shallow_resolve` just ignores anything that is not a type
// variable, and because type variable's can't (at present, at
// least) capture any of the things bound by this binder.
//
// Really, there is no *particular* reason to do this
// `shallow_resolve_type` here except as a
// `shallow_resolve` here except as a
// micro-optimization. Naturally I could not
// resist. -nmatsakis
let two_unbound_type_vars = {
let a = self.shallow_resolve_type(predicate.skip_binder().a);
let b = self.shallow_resolve_type(predicate.skip_binder().b);
let a = self.shallow_resolve(predicate.skip_binder().a);
let b = self.shallow_resolve(predicate.skip_binder().b);
a.is_ty_var() && b.is_ty_var()
};
@ -1274,46 +1274,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.resolve_type_vars_if_possible(t).to_string()
}
// We have this force-inlined variant of `shallow_resolve_type` for the one
// callsite that is extremely hot. All other callsites use the normal
// variant.
#[inline(always)]
pub fn inlined_shallow_resolve_type(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
match typ.sty {
ty::Infer(ty::TyVar(v)) => {
// Not entirely obvious: if `typ` is a type variable,
// it can be resolved to an int/float variable, which
// can then be recursively resolved, hence the
// recursion. Note though that we prevent type
// variables from unifyxing to other type variables
// directly (though they may be embedded
// structurally), and we prevent cycles in any case,
// so this recursion should always be of very limited
// depth.
self.type_variables
.borrow_mut()
.probe(v)
.known()
.map(|t| self.shallow_resolve_type(t))
.unwrap_or(typ)
}
ty::Infer(ty::IntVar(v)) => self.int_unification_table
.borrow_mut()
.probe_value(v)
.map(|v| v.to_type(self.tcx))
.unwrap_or(typ),
ty::Infer(ty::FloatVar(v)) => self.float_unification_table
.borrow_mut()
.probe_value(v)
.map(|v| v.to_type(self.tcx))
.unwrap_or(typ),
_ => typ,
}
}
/// If `TyVar(vid)` resolves to a type, return that type. Else, return the
/// universe index of `TyVar(vid)`.
pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, ty::UniverseIndex> {
@ -1325,8 +1285,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}
pub fn shallow_resolve_type(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
self.inlined_shallow_resolve_type(typ)
pub fn shallow_resolve<T>(&self, value: T) -> T
where
T: TypeFoldable<'tcx>,
{
let mut r = ShallowResolver::new(self);
value.fold_with(&mut r)
}
pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
@ -1391,24 +1355,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}
pub fn shallow_resolve_const(
&self,
ct: &'tcx ty::Const<'tcx>
) -> &'tcx ty::Const<'tcx> {
match ct {
ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } => {
self.const_unification_table
.borrow_mut()
.probe_value(*vid)
.val
.known()
.map(|c| self.shallow_resolve_const(c))
.unwrap_or(ct)
}
_ => ct,
}
}
pub fn fully_resolve<T: TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<'tcx, T> {
/*!
* Attempts to resolve all type/region/const variables in
@ -1528,7 +1474,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
closure_substs: ty::ClosureSubsts<'tcx>,
) -> Option<ty::ClosureKind> {
let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx);
let closure_kind_ty = self.shallow_resolve_type(&closure_kind_ty);
let closure_kind_ty = self.shallow_resolve(closure_kind_ty);
closure_kind_ty.to_opt_closure_kind()
}
@ -1542,7 +1488,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
substs: ty::ClosureSubsts<'tcx>,
) -> ty::PolyFnSig<'tcx> {
let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx);
let closure_sig_ty = self.shallow_resolve_type(&closure_sig_ty);
let closure_sig_ty = self.shallow_resolve(closure_sig_ty);
closure_sig_ty.fn_sig(self.tcx)
}
@ -1598,6 +1544,82 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}
pub struct ShallowResolver<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
}
impl<'a, 'gcx, 'tcx> ShallowResolver<'a, 'gcx, 'tcx> {
#[inline(always)]
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
ShallowResolver { infcx }
}
// We have this force-inlined variant of `shallow_resolve` for the one
// callsite that is extremely hot. All other callsites use the normal
// variant.
#[inline(always)]
pub fn inlined_shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> {
match typ.sty {
ty::Infer(ty::TyVar(v)) => {
// Not entirely obvious: if `typ` is a type variable,
// it can be resolved to an int/float variable, which
// can then be recursively resolved, hence the
// recursion. Note though that we prevent type
// variables from unifyxing to other type variables
// directly (though they may be embedded
// structurally), and we prevent cycles in any case,
// so this recursion should always be of very limited
// depth.
self.infcx.type_variables
.borrow_mut()
.probe(v)
.known()
.map(|t| self.fold_ty(t))
.unwrap_or(typ)
}
ty::Infer(ty::IntVar(v)) => self.infcx.int_unification_table
.borrow_mut()
.probe_value(v)
.map(|v| v.to_type(self.infcx.tcx))
.unwrap_or(typ),
ty::Infer(ty::FloatVar(v)) => self.infcx.float_unification_table
.borrow_mut()
.probe_value(v)
.map(|v| v.to_type(self.infcx.tcx))
.unwrap_or(typ),
_ => typ,
}
}
}
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ShallowResolver<'a, 'gcx, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
self.infcx.tcx
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
self.inlined_shallow_resolve(ty)
}
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
match ct {
ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } => {
self.infcx.const_unification_table
.borrow_mut()
.probe_value(*vid)
.val
.known()
.map(|c| self.fold_const(c))
.unwrap_or(ct)
}
_ => ct,
}
}
}
impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> {
pub fn span(&self) -> Span {
self.cause.span