Skip to content

Commit

Permalink
Reduce the number of RefCells in InferCtxt.
Browse files Browse the repository at this point in the history
`InferCtxt` contains six structures within `RefCell`s. Every time we
create and dispose of (commit or rollback) a snapshot we have to
`borrow_mut` each one of them.

This commit moves the six structures under a single `RefCell`, which
gives significant speed-ups by reducing the number of `borrow_mut`
calls. To avoid runtime errors I had to reduce the lifetimes of dynamic
borrows in a couple of places.
  • Loading branch information
nnethercote committed Feb 9, 2020
1 parent a19edd6 commit 7426853
Show file tree
Hide file tree
Showing 20 changed files with 321 additions and 242 deletions.
6 changes: 4 additions & 2 deletions src/librustc/infer/canonical/canonicalizer.rs
Expand Up @@ -317,7 +317,9 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
let r = self
.infcx
.unwrap()
.borrow_region_constraints()
.inner
.borrow_mut()
.unwrap_region_constraints()
.opportunistic_resolve_var(self.tcx, vid);
debug!(
"canonical: region var found with vid {:?}, \
Expand Down Expand Up @@ -621,7 +623,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {

/// Returns the universe in which `vid` is defined.
fn region_var_universe(&self, vid: ty::RegionVid) -> ty::UniverseIndex {
self.infcx.unwrap().borrow_region_constraints().var_universe(vid)
self.infcx.unwrap().inner.borrow_mut().unwrap_region_constraints().var_universe(vid)
}

/// Creates a canonical variable (with the given `info`)
Expand Down
50 changes: 30 additions & 20 deletions src/librustc/infer/combine.rs
Expand Up @@ -74,8 +74,9 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
match (&a.kind, &b.kind) {
// Relate integral variables to other types
(&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => {
self.int_unification_table
self.inner
.borrow_mut()
.int_unification_table
.unify_var_var(a_id, b_id)
.map_err(|e| int_unification_error(a_is_expected, e))?;
Ok(a)
Expand All @@ -95,8 +96,9 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {

// Relate floating-point variables to other types
(&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => {
self.float_unification_table
self.inner
.borrow_mut()
.float_unification_table
.unify_var_var(a_id, b_id)
.map_err(|e| float_unification_error(relation.a_is_expected(), e))?;
Ok(a)
Expand Down Expand Up @@ -131,8 +133,8 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
return Ok(a);
}

let a = replace_if_possible(self.const_unification_table.borrow_mut(), a);
let b = replace_if_possible(self.const_unification_table.borrow_mut(), b);
let a = replace_if_possible(&mut self.inner.borrow_mut().const_unification_table, a);
let b = replace_if_possible(&mut self.inner.borrow_mut().const_unification_table, b);

let a_is_expected = relation.a_is_expected();

Expand All @@ -141,8 +143,9 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
ty::ConstKind::Infer(InferConst::Var(a_vid)),
ty::ConstKind::Infer(InferConst::Var(b_vid)),
) => {
self.const_unification_table
self.inner
.borrow_mut()
.const_unification_table
.unify_var_var(a_vid, b_vid)
.map_err(|e| const_unification_error(a_is_expected, e))?;
return Ok(a);
Expand Down Expand Up @@ -174,8 +177,9 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
vid: ty::ConstVid<'tcx>,
value: &'tcx ty::Const<'tcx>,
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
self.const_unification_table
self.inner
.borrow_mut()
.const_unification_table
.unify_var_value(
vid,
ConstVarValue {
Expand All @@ -196,8 +200,9 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
vid: ty::IntVid,
val: ty::IntVarValue,
) -> RelateResult<'tcx, Ty<'tcx>> {
self.int_unification_table
self.inner
.borrow_mut()
.int_unification_table
.unify_var_value(vid, Some(val))
.map_err(|e| int_unification_error(vid_is_expected, e))?;
match val {
Expand All @@ -212,8 +217,9 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
vid: ty::FloatVid,
val: ast::FloatTy,
) -> RelateResult<'tcx, Ty<'tcx>> {
self.float_unification_table
self.inner
.borrow_mut()
.float_unification_table
.unify_var_value(vid, Some(ty::FloatVarValue(val)))
.map_err(|e| float_unification_error(vid_is_expected, e))?;
Ok(self.tcx.mk_mach_float(val))
Expand Down Expand Up @@ -260,7 +266,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
use self::RelationDir::*;

// Get the actual variable that b_vid has been inferred to
debug_assert!(self.infcx.type_variables.borrow_mut().probe(b_vid).is_unknown());
debug_assert!(self.infcx.inner.borrow_mut().type_variables.probe(b_vid).is_unknown());

debug!("instantiate(a_ty={:?} dir={:?} b_vid={:?})", a_ty, dir, b_vid);

Expand All @@ -280,7 +286,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
"instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})",
a_ty, dir, b_vid, b_ty
);
self.infcx.type_variables.borrow_mut().instantiate(b_vid, b_ty);
self.infcx.inner.borrow_mut().type_variables.instantiate(b_vid, b_ty);

if needs_wf {
self.obligations.push(Obligation::new(
Expand Down Expand Up @@ -338,7 +344,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {

debug!("generalize: ambient_variance = {:?}", ambient_variance);

let for_universe = match self.infcx.type_variables.borrow_mut().probe(for_vid) {
let for_universe = match self.infcx.inner.borrow_mut().type_variables.probe(for_vid) {
v @ TypeVariableValue::Known { .. } => {
panic!("instantiating {:?} which has a known value {:?}", for_vid, v,)
}
Expand All @@ -350,7 +356,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
let mut generalize = Generalizer {
infcx: self.infcx,
span: self.trace.cause.span,
for_vid_sub_root: self.infcx.type_variables.borrow_mut().sub_root_var(for_vid),
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables.sub_root_var(for_vid),
for_universe,
ambient_variance,
needs_wf: false,
Expand Down Expand Up @@ -502,17 +508,16 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
// us from creating infinitely sized types.
match t.kind {
ty::Infer(ty::TyVar(vid)) => {
let mut variables = self.infcx.type_variables.borrow_mut();
let vid = variables.root_var(vid);
let sub_vid = variables.sub_root_var(vid);
let vid = self.infcx.inner.borrow_mut().type_variables.root_var(vid);
let sub_vid = self.infcx.inner.borrow_mut().type_variables.sub_root_var(vid);
if sub_vid == self.for_vid_sub_root {
// If sub-roots are equal, then `for_vid` and
// `vid` are related via subtyping.
Err(TypeError::CyclicTy(self.root_ty))
} else {
match variables.probe(vid) {
let probe = self.infcx.inner.borrow_mut().type_variables.probe(vid);
match probe {
TypeVariableValue::Known { value: u } => {
drop(variables);
debug!("generalize: known value {:?}", u);
self.relate(&u, &u)
}
Expand All @@ -536,8 +541,13 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
ty::Covariant | ty::Contravariant => (),
}

let origin = *variables.var_origin(vid);
let new_var_id = variables.new_var(self.for_universe, false, origin);
let origin =
*self.infcx.inner.borrow_mut().type_variables.var_origin(vid);
let new_var_id = self.infcx.inner.borrow_mut().type_variables.new_var(
self.for_universe,
false,
origin,
);
let u = self.tcx().mk_ty_var(new_var_id);
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
Ok(u)
Expand Down Expand Up @@ -612,7 +622,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {

match c.val {
ty::ConstKind::Infer(InferConst::Var(vid)) => {
let mut variable_table = self.infcx.const_unification_table.borrow_mut();
let variable_table = &mut self.infcx.inner.borrow_mut().const_unification_table;
let var_value = variable_table.probe_value(vid);
match var_value.val {
ConstVariableValue::Known { value: u } => self.relate(&u, &u),
Expand Down
13 changes: 9 additions & 4 deletions src/librustc/infer/equate.rs
Expand Up @@ -72,14 +72,14 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> {
}

let infcx = self.fields.infcx;
let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
let a = infcx.inner.borrow_mut().type_variables.replace_if_possible(a);
let b = infcx.inner.borrow_mut().type_variables.replace_if_possible(b);

debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b);

match (&a.kind, &b.kind) {
(&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
infcx.type_variables.borrow_mut().equate(a_id, b_id);
infcx.inner.borrow_mut().type_variables.equate(a_id, b_id);
}

(&ty::Infer(TyVar(a_id)), _) => {
Expand All @@ -105,7 +105,12 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> {
) -> RelateResult<'tcx, ty::Region<'tcx>> {
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
let origin = Subtype(box self.fields.trace.clone());
self.fields.infcx.borrow_region_constraints().make_eqregion(origin, a, b);
self.fields
.infcx
.inner
.borrow_mut()
.unwrap_region_constraints()
.make_eqregion(origin, a, b);
Ok(a)
}

Expand Down
13 changes: 8 additions & 5 deletions src/librustc/infer/error_reporting/need_type_info.rs
Expand Up @@ -47,9 +47,12 @@ impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
if ty.walk().any(|inner_ty| {
inner_ty == self.target_ty
|| match (&inner_ty.kind, &self.target_ty.kind) {
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
self.infcx.type_variables.borrow_mut().sub_unified(a_vid, b_vid)
}
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => self
.infcx
.inner
.borrow_mut()
.type_variables
.sub_unified(a_vid, b_vid),
_ => false,
}
}) {
Expand Down Expand Up @@ -166,7 +169,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
highlight: Option<ty::print::RegionHighlightMode>,
) -> (String, Option<Span>, Cow<'static, str>, Option<String>, Option<&'static str>) {
if let ty::Infer(ty::TyVar(ty_vid)) = ty.kind {
let ty_vars = self.type_variables.borrow();
let ty_vars = &self.inner.borrow().type_variables;
let var_origin = ty_vars.var_origin(ty_vid);
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind {
let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id));
Expand Down Expand Up @@ -224,7 +227,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let ty_to_string = |ty: Ty<'tcx>| -> String {
let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
let ty_vars = self.type_variables.borrow();
let ty_vars = &self.inner.borrow().type_variables;
let getter = move |ty_vid| {
let var_origin = ty_vars.var_origin(ty_vid);
if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind {
Expand Down
18 changes: 13 additions & 5 deletions src/librustc/infer/freshen.rs
Expand Up @@ -154,14 +154,15 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {

match t.kind {
ty::Infer(ty::TyVar(v)) => {
let opt_ty = self.infcx.type_variables.borrow_mut().probe(v).known();
let opt_ty = self.infcx.inner.borrow_mut().type_variables.probe(v).known();
self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy)
}

ty::Infer(ty::IntVar(v)) => self.freshen_ty(
self.infcx
.int_unification_table
.inner
.borrow_mut()
.int_unification_table
.probe_value(v)
.map(|v| v.to_type(tcx)),
ty::IntVar(v),
Expand All @@ -170,8 +171,9 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {

ty::Infer(ty::FloatVar(v)) => self.freshen_ty(
self.infcx
.float_unification_table
.inner
.borrow_mut()
.float_unification_table
.probe_value(v)
.map(|v| v.to_type(tcx)),
ty::FloatVar(v),
Expand Down Expand Up @@ -225,8 +227,14 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
match ct.val {
ty::ConstKind::Infer(ty::InferConst::Var(v)) => {
let opt_ct =
self.infcx.const_unification_table.borrow_mut().probe_value(v).val.known();
let opt_ct = self
.infcx
.inner
.borrow_mut()
.const_unification_table
.probe_value(v)
.val
.known();
return self.freshen_const(
opt_ct,
ty::InferConst::Var(v),
Expand Down
32 changes: 14 additions & 18 deletions src/librustc/infer/fudge.rs
Expand Up @@ -8,11 +8,10 @@ use super::{ConstVariableOrigin, RegionVariableOrigin};
use rustc_data_structures::unify as ut;
use ut::UnifyKey;

use std::cell::RefMut;
use std::ops::Range;

fn const_vars_since_snapshot<'tcx>(
mut table: RefMut<'_, ut::UnificationTable<ut::InPlace<ConstVid<'tcx>>>>,
table: &mut ut::UnificationTable<ut::InPlace<ConstVid<'tcx>>>,
snapshot: &ut::Snapshot<ut::InPlace<ConstVid<'tcx>>>,
) -> (Range<ConstVid<'tcx>>, Vec<ConstVariableOrigin>) {
let range = table.vars_since_snapshot(snapshot);
Expand Down Expand Up @@ -82,23 +81,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// going to be popped, so we will have to
// eliminate any references to them.

let type_vars = self
.type_variables
.borrow_mut()
.vars_since_snapshot(&snapshot.type_snapshot);
let int_vars = self
.int_unification_table
.borrow_mut()
.vars_since_snapshot(&snapshot.int_snapshot);
let float_vars = self
.float_unification_table
.borrow_mut()
.vars_since_snapshot(&snapshot.float_snapshot);
let region_vars = self
.borrow_region_constraints()
let mut inner = self.inner.borrow_mut();
let type_vars =
inner.type_variables.vars_since_snapshot(&snapshot.type_snapshot);
let int_vars =
inner.int_unification_table.vars_since_snapshot(&snapshot.int_snapshot);
let float_vars =
inner.float_unification_table.vars_since_snapshot(&snapshot.float_snapshot);
let region_vars = inner
.unwrap_region_constraints()
.vars_since_snapshot(&snapshot.region_constraints_snapshot);
let const_vars = const_vars_since_snapshot(
self.const_unification_table.borrow_mut(),
&mut inner.const_unification_table,
&snapshot.const_snapshot,
);

Expand Down Expand Up @@ -166,7 +160,9 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> {
// variables to their binding anyhow, we know
// that it is unbound, so we can just return
// it.
debug_assert!(self.infcx.type_variables.borrow_mut().probe(vid).is_unknown());
debug_assert!(
self.infcx.inner.borrow_mut().type_variables.probe(vid).is_unknown()
);
ty
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/librustc/infer/glb.rs
Expand Up @@ -66,7 +66,12 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> {
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);

let origin = Subtype(box self.fields.trace.clone());
Ok(self.fields.infcx.borrow_region_constraints().glb_regions(self.tcx(), origin, a, b))
Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
self.tcx(),
origin,
a,
b,
))
}

fn consts(
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/infer/higher_ranked/mod.rs
Expand Up @@ -138,7 +138,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
return Ok(());
}

self.borrow_region_constraints().leak_check(
self.inner.borrow_mut().unwrap_region_constraints().leak_check(
self.tcx,
overly_polymorphic,
placeholder_map,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/infer/lattice.rs
Expand Up @@ -56,8 +56,8 @@ where
}

let infcx = this.infcx();
let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
let a = infcx.inner.borrow_mut().type_variables.replace_if_possible(a);
let b = infcx.inner.borrow_mut().type_variables.replace_if_possible(b);
match (&a.kind, &b.kind) {
// If one side is known to be a variable and one is not,
// create a variable (`v`) to represent the LUB. Make sure to
Expand Down
7 changes: 6 additions & 1 deletion src/librustc/infer/lub.rs
Expand Up @@ -66,7 +66,12 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> {
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);

let origin = Subtype(box self.fields.trace.clone());
Ok(self.fields.infcx.borrow_region_constraints().lub_regions(self.tcx(), origin, a, b))
Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().lub_regions(
self.tcx(),
origin,
a,
b,
))
}

fn consts(
Expand Down

0 comments on commit 7426853

Please sign in to comment.