Skip to content

Commit

Permalink
infer: export methods on InferCtxt instead of ShallowResolver.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Mar 21, 2020
1 parent 5f13820 commit d8448d2
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 38 deletions.
61 changes: 26 additions & 35 deletions src/librustc_infer/infer/mod.rs
Expand Up @@ -1347,8 +1347,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
where
T: TypeFoldable<'tcx>,
{
let mut r = ShallowResolver::new(self);
value.fold_with(&mut r)
value.fold_with(&mut ShallowResolver { infcx: self })
}

pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
Expand Down Expand Up @@ -1565,22 +1564,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// variables, thus we don't need to substitute back the original values.
self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, span)
}
}

pub struct ShallowResolver<'a, 'tcx> {
infcx: &'a InferCtxt<'a, 'tcx>,
}

impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
#[inline(always)]
pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
ShallowResolver { infcx }
}

/// If `typ` is a type variable of some kind, resolve it one level
/// (but do not resolve types found in the result). If `typ` is
/// not a type variable, just return it unmodified.
pub fn shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> {
// FIXME(eddyb) inline into `ShallowResolver::visit_ty`.
fn shallow_resolve_ty(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
match typ.kind {
ty::Infer(ty::TyVar(v)) => {
// Not entirely obvious: if `typ` is a type variable,
Expand All @@ -1594,78 +1583,80 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
// depth.
//
// Note: if these two lines are combined into one we get
// dynamic borrow errors on `self.infcx.inner`.
let known = self.infcx.inner.borrow_mut().type_variables.probe(v).known();
known.map(|t| self.fold_ty(t)).unwrap_or(typ)
// dynamic borrow errors on `self.inner`.
let known = self.inner.borrow_mut().type_variables.probe(v).known();
known.map(|t| self.shallow_resolve_ty(t)).unwrap_or(typ)
}

ty::Infer(ty::IntVar(v)) => self
.infcx
.inner
.borrow_mut()
.int_unification_table
.probe_value(v)
.map(|v| v.to_type(self.infcx.tcx))
.map(|v| v.to_type(self.tcx))
.unwrap_or(typ),

ty::Infer(ty::FloatVar(v)) => self
.infcx
.inner
.borrow_mut()
.float_unification_table
.probe_value(v)
.map(|v| v.to_type(self.infcx.tcx))
.map(|v| v.to_type(self.tcx))
.unwrap_or(typ),

_ => typ,
}
}

// `resolver.shallow_resolve_changed(ty)` is equivalent to
// `resolver.shallow_resolve(ty) != ty`, but more efficient. It's always
// inlined, despite being large, because it has only two call sites that
// are extremely hot.
/// `infer_ty_changed(infer_ty)` is equivalent to `shallow_resolve(ty) != ty`
/// (where `ty.kind = ty::Infer(infer_ty)`), but more efficient. It's always
/// inlined, despite being large, because it has only two call sites that
/// are extremely hot.
#[inline(always)]
pub fn shallow_resolve_changed(&self, infer: ty::InferTy) -> bool {
match infer {
pub fn infer_ty_changed(&self, infer_ty: ty::InferTy) -> bool {
match infer_ty {
ty::TyVar(v) => {
use self::type_variable::TypeVariableValue;

// If `inlined_probe` returns a `Known` value its `kind` never
// matches `infer`.
match self.infcx.inner.borrow_mut().type_variables.inlined_probe(v) {
// If `inlined_probe` returns a `Known` value, it never equals
// `ty::Infer(ty::TyVar(v))`.
match self.inner.borrow_mut().type_variables.inlined_probe(v) {
TypeVariableValue::Unknown { .. } => false,
TypeVariableValue::Known { .. } => true,
}
}

ty::IntVar(v) => {
// If inlined_probe_value returns a value it's always a
// If `inlined_probe_value` returns a value it's always a
// `ty::Int(_)` or `ty::UInt(_)`, which never matches a
// `ty::Infer(_)`.
self.infcx.inner.borrow_mut().int_unification_table.inlined_probe_value(v).is_some()
self.inner.borrow_mut().int_unification_table.inlined_probe_value(v).is_some()
}

ty::FloatVar(v) => {
// If inlined_probe_value returns a value it's always a
// If `inlined_probe_value` returns a value it's always a
// `ty::Float(_)`, which never matches a `ty::Infer(_)`.
//
// Not `inlined_probe_value(v)` because this call site is colder.
self.infcx.inner.borrow_mut().float_unification_table.probe_value(v).is_some()
self.inner.borrow_mut().float_unification_table.probe_value(v).is_some()
}

_ => unreachable!(),
}
}
}

struct ShallowResolver<'a, 'tcx> {
infcx: &'a InferCtxt<'a, 'tcx>,
}

impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
self.infcx.tcx
}

fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
self.shallow_resolve(ty)
self.infcx.shallow_resolve_ty(ty)
}

fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_trait_selection/traits/fulfill.rs
@@ -1,4 +1,4 @@
use crate::infer::{InferCtxt, ShallowResolver};
use crate::infer::InferCtxt;
use rustc::ty::error::ExpectedFound;
use rustc::ty::{self, ToPolyTraitRef, Ty, TypeFoldable};
use rustc_data_structures::obligation_forest::ProcessResult;
Expand Down Expand Up @@ -267,7 +267,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
// code is so hot. 1 and 0 dominate; 2+ is fairly rare.
1 => {
let infer = pending_obligation.stalled_on[0];
ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer)
self.selcx.infcx().infer_ty_changed(infer)
}
0 => {
// In this case we haven't changed, but wish to make a change.
Expand All @@ -278,7 +278,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
// form was a perf win. See #64545 for details.
(|| {
for &infer in &pending_obligation.stalled_on {
if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer) {
if self.selcx.infcx().infer_ty_changed(infer) {
return true;
}
}
Expand Down

0 comments on commit d8448d2

Please sign in to comment.