Rollup merge of #68694 - nnethercote:reduce-RefCells-in-InferCtxt, r=varkor

Reduce the number of `RefCell`s in `InferCtxt`.

`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.

r? @varkor
This commit is contained in:
Dylan DPC 2020-02-10 01:54:15 +01:00 committed by GitHub
commit 8007f8468b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 321 additions and 242 deletions

View File

@ -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 {:?}, \
@ -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`)

View File

@ -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)
@ -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)
@ -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();
@ -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);
@ -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 {
@ -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 {
@ -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))
@ -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);
@ -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(
@ -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,)
}
@ -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,
@ -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)
}
@ -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)
@ -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),

View File

@ -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)), _) => {
@ -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)
}

View File

@ -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,
}
}) {
@ -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));
@ -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 {

View File

@ -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),
@ -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),
@ -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),

View File

@ -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);
@ -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,
);
@ -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
}
}

View File

@ -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(

View File

@ -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,

View File

@ -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

View File

@ -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(

View File

@ -29,7 +29,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use std::cell::{Cell, Ref, RefCell, RefMut};
use std::cell::{Cell, Ref, RefCell};
use std::collections::BTreeMap;
use std::fmt;
use syntax::ast;
@ -105,6 +105,89 @@ impl SuppressRegionErrors {
}
}
/// This type contains all the things within `InferCtxt` that sit within a
/// `RefCell` and are involved with taking/rolling back snapshots. Snapshot
/// operations are hot enough that we want only one call to `borrow_mut` per
/// call to `start_snapshot` and `rollback_to`.
pub struct InferCtxtInner<'tcx> {
/// Cache for projections. This cache is snapshotted along with the infcx.
///
/// Public so that `traits::project` can use it.
pub projection_cache: traits::ProjectionCache<'tcx>,
/// We instantiate `UnificationTable` with `bounds<Ty>` because the types
/// that might instantiate a general type variable have an order,
/// represented by its upper and lower bounds.
type_variables: type_variable::TypeVariableTable<'tcx>,
/// Map from const parameter variable to the kind of const it represents.
const_unification_table: ut::UnificationTable<ut::InPlace<ty::ConstVid<'tcx>>>,
/// Map from integral variable to the kind of integer it represents.
int_unification_table: ut::UnificationTable<ut::InPlace<ty::IntVid>>,
/// Map from floating variable to the kind of float it represents.
float_unification_table: ut::UnificationTable<ut::InPlace<ty::FloatVid>>,
/// Tracks the set of region variables and the constraints between them.
/// This is initially `Some(_)` but when
/// `resolve_regions_and_report_errors` is invoked, this gets set to `None`
/// -- further attempts to perform unification, etc., may fail if new
/// region constraints would've been added.
region_constraints: Option<RegionConstraintCollector<'tcx>>,
/// A set of constraints that regionck must validate. Each
/// constraint has the form `T:'a`, meaning "some type `T` must
/// outlive the lifetime 'a". These constraints derive from
/// instantiated type parameters. So if you had a struct defined
/// like
///
/// struct Foo<T:'static> { ... }
///
/// then in some expression `let x = Foo { ... }` it will
/// instantiate the type parameter `T` with a fresh type `$0`. At
/// the same time, it will record a region obligation of
/// `$0:'static`. This will get checked later by regionck. (We
/// can't generally check these things right away because we have
/// to wait until types are resolved.)
///
/// These are stored in a map keyed to the id of the innermost
/// enclosing fn body / static initializer expression. This is
/// because the location where the obligation was incurred can be
/// relevant with respect to which sublifetime assumptions are in
/// place. The reason that we store under the fn-id, and not
/// something more fine-grained, is so that it is easier for
/// regionck to be sure that it has found *all* the region
/// obligations (otherwise, it's easy to fail to walk to a
/// particular node-id).
///
/// Before running `resolve_regions_and_report_errors`, the creator
/// of the inference context is expected to invoke
/// `process_region_obligations` (defined in `self::region_obligations`)
/// for each body-id in this map, which will process the
/// obligations within. This is expected to be done 'late enough'
/// that all type inference variables have been bound and so forth.
pub region_obligations: Vec<(hir::HirId, RegionObligation<'tcx>)>,
}
impl<'tcx> InferCtxtInner<'tcx> {
fn new() -> InferCtxtInner<'tcx> {
InferCtxtInner {
projection_cache: Default::default(),
type_variables: type_variable::TypeVariableTable::new(),
const_unification_table: ut::UnificationTable::new(),
int_unification_table: ut::UnificationTable::new(),
float_unification_table: ut::UnificationTable::new(),
region_constraints: Some(RegionConstraintCollector::new()),
region_obligations: vec![],
}
}
pub fn unwrap_region_constraints(&mut self) -> &mut RegionConstraintCollector<'tcx> {
self.region_constraints.as_mut().expect("region constraints already solved")
}
}
pub struct InferCtxt<'a, 'tcx> {
pub tcx: TyCtxt<'tcx>,
@ -114,16 +197,7 @@ pub struct InferCtxt<'a, 'tcx> {
/// and for error reporting logic to read arbitrary node types.
pub in_progress_tables: Option<&'a RefCell<ty::TypeckTables<'tcx>>>,
/// Cache for projections. This cache is snapshotted along with the
/// infcx.
///
/// Public so that `traits::project` can use it.
pub projection_cache: RefCell<traits::ProjectionCache<'tcx>>,
/// We instantiate `UnificationTable` with `bounds<Ty>` because the
/// types that might instantiate a general type variable have an
/// order, represented by its upper and lower bounds.
pub type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
pub inner: RefCell<InferCtxtInner<'tcx>>,
/// If set, this flag causes us to skip the 'leak check' during
/// higher-ranked subtyping operations. This flag is a temporary one used
@ -132,22 +206,6 @@ pub struct InferCtxt<'a, 'tcx> {
/// when entering a snapshot.
skip_leak_check: Cell<bool>,
/// Map from const parameter variable to the kind of const it represents.
const_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::ConstVid<'tcx>>>>,
/// Map from integral variable to the kind of integer it represents.
int_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::IntVid>>>,
/// Map from floating variable to the kind of float it represents
float_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::FloatVid>>>,
/// Tracks the set of region variables and the constraints between
/// them. This is initially `Some(_)` but when
/// `resolve_regions_and_report_errors` is invoked, this gets set
/// to `None` -- further attempts to perform unification etc may
/// fail if new region constraints would've been added.
region_constraints: RefCell<Option<RegionConstraintCollector<'tcx>>>,
/// Once region inference is done, the values for each variable.
lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,
@ -189,39 +247,6 @@ pub struct InferCtxt<'a, 'tcx> {
/// This flag is true while there is an active snapshot.
in_snapshot: Cell<bool>,
/// A set of constraints that regionck must validate. Each
/// constraint has the form `T:'a`, meaning "some type `T` must
/// outlive the lifetime 'a". These constraints derive from
/// instantiated type parameters. So if you had a struct defined
/// like
///
/// struct Foo<T:'static> { ... }
///
/// then in some expression `let x = Foo { ... }` it will
/// instantiate the type parameter `T` with a fresh type `$0`. At
/// the same time, it will record a region obligation of
/// `$0:'static`. This will get checked later by regionck. (We
/// can't generally check these things right away because we have
/// to wait until types are resolved.)
///
/// These are stored in a map keyed to the id of the innermost
/// enclosing fn body / static initializer expression. This is
/// because the location where the obligation was incurred can be
/// relevant with respect to which sublifetime assumptions are in
/// place. The reason that we store under the fn-id, and not
/// something more fine-grained, is so that it is easier for
/// regionck to be sure that it has found *all* the region
/// obligations (otherwise, it's easy to fail to walk to a
/// particular node-id).
///
/// Before running `resolve_regions_and_report_errors`, the creator
/// of the inference context is expected to invoke
/// `process_region_obligations` (defined in `self::region_obligations`)
/// for each body-id in this map, which will process the
/// obligations within. This is expected to be done 'late enough'
/// that all type inference variables have been bound and so forth.
pub region_obligations: RefCell<Vec<(hir::HirId, RegionObligation<'tcx>)>>,
/// What is the innermost universe we have created? Starts out as
/// `UniverseIndex::root()` but grows from there as we enter
/// universal quantifiers.
@ -543,12 +568,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
f(InferCtxt {
tcx,
in_progress_tables,
projection_cache: Default::default(),
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
const_unification_table: RefCell::new(ut::UnificationTable::new()),
int_unification_table: RefCell::new(ut::UnificationTable::new()),
float_unification_table: RefCell::new(ut::UnificationTable::new()),
region_constraints: RefCell::new(Some(RegionConstraintCollector::new())),
inner: RefCell::new(InferCtxtInner::new()),
lexical_region_resolutions: RefCell::new(None),
selection_cache: Default::default(),
evaluation_cache: Default::default(),
@ -558,7 +578,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
err_count_on_creation: tcx.sess.err_count(),
in_snapshot: Cell::new(false),
skip_leak_check: Cell::new(false),
region_obligations: RefCell::new(vec![]),
universe: Cell::new(ty::UniverseIndex::ROOT),
})
})
@ -616,7 +635,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn type_var_diverges(&'a self, ty: Ty<'_>) -> bool {
match ty.kind {
ty::Infer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid),
ty::Infer(ty::TyVar(vid)) => self.inner.borrow().type_variables.var_diverges(vid),
_ => false,
}
}
@ -630,14 +649,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
use crate::ty::error::UnconstrainedNumeric::{UnconstrainedFloat, UnconstrainedInt};
match ty.kind {
ty::Infer(ty::IntVar(vid)) => {
if self.int_unification_table.borrow_mut().probe_value(vid).is_some() {
if self.inner.borrow_mut().int_unification_table.probe_value(vid).is_some() {
Neither
} else {
UnconstrainedInt
}
}
ty::Infer(ty::FloatVar(vid)) => {
if self.float_unification_table.borrow_mut().probe_value(vid).is_some() {
if self.inner.borrow_mut().float_unification_table.probe_value(vid).is_some() {
Neither
} else {
UnconstrainedFloat
@ -648,28 +667,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
pub fn unsolved_variables(&self) -> Vec<Ty<'tcx>> {
let mut type_variables = self.type_variables.borrow_mut();
let mut int_unification_table = self.int_unification_table.borrow_mut();
let mut float_unification_table = self.float_unification_table.borrow_mut();
let mut inner = self.inner.borrow_mut();
// FIXME(const_generics): should there be an equivalent function for const variables?
type_variables
let mut vars: Vec<Ty<'_>> = inner
.type_variables
.unsolved_variables()
.into_iter()
.map(|t| self.tcx.mk_ty_var(t))
.chain(
(0..int_unification_table.len())
.map(|i| ty::IntVid { index: i as u32 })
.filter(|&vid| int_unification_table.probe_value(vid).is_none())
.map(|v| self.tcx.mk_int_var(v)),
)
.chain(
(0..float_unification_table.len())
.map(|i| ty::FloatVid { index: i as u32 })
.filter(|&vid| float_unification_table.probe_value(vid).is_none())
.map(|v| self.tcx.mk_float_var(v)),
)
.collect()
.collect();
vars.extend(
(0..inner.int_unification_table.len())
.map(|i| ty::IntVid { index: i as u32 })
.filter(|&vid| inner.int_unification_table.probe_value(vid).is_none())
.map(|v| self.tcx.mk_int_var(v)),
);
vars.extend(
(0..inner.float_unification_table.len())
.map(|i| ty::FloatVid { index: i as u32 })
.filter(|&vid| inner.float_unification_table.probe_value(vid).is_none())
.map(|v| self.tcx.mk_float_var(v)),
);
vars
}
fn combine_fields(
@ -719,14 +738,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let in_snapshot = self.in_snapshot.get();
self.in_snapshot.set(true);
let mut inner = self.inner.borrow_mut();
CombinedSnapshot {
projection_cache_snapshot: self.projection_cache.borrow_mut().snapshot(),
type_snapshot: self.type_variables.borrow_mut().snapshot(),
const_snapshot: self.const_unification_table.borrow_mut().snapshot(),
int_snapshot: self.int_unification_table.borrow_mut().snapshot(),
float_snapshot: self.float_unification_table.borrow_mut().snapshot(),
region_constraints_snapshot: self.borrow_region_constraints().start_snapshot(),
region_obligations_snapshot: self.region_obligations.borrow().len(),
projection_cache_snapshot: inner.projection_cache.snapshot(),
type_snapshot: inner.type_variables.snapshot(),
const_snapshot: inner.const_unification_table.snapshot(),
int_snapshot: inner.int_unification_table.snapshot(),
float_snapshot: inner.float_unification_table.snapshot(),
region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
region_obligations_snapshot: inner.region_obligations.len(),
universe: self.universe(),
was_in_snapshot: in_snapshot,
was_skip_leak_check: self.skip_leak_check.get(),
@ -756,13 +776,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.universe.set(universe);
self.skip_leak_check.set(was_skip_leak_check);
self.projection_cache.borrow_mut().rollback_to(projection_cache_snapshot);
self.type_variables.borrow_mut().rollback_to(type_snapshot);
self.const_unification_table.borrow_mut().rollback_to(const_snapshot);
self.int_unification_table.borrow_mut().rollback_to(int_snapshot);
self.float_unification_table.borrow_mut().rollback_to(float_snapshot);
self.region_obligations.borrow_mut().truncate(region_obligations_snapshot);
self.borrow_region_constraints().rollback_to(region_constraints_snapshot);
let mut inner = self.inner.borrow_mut();
inner.projection_cache.rollback_to(projection_cache_snapshot);
inner.type_variables.rollback_to(type_snapshot);
inner.const_unification_table.rollback_to(const_snapshot);
inner.int_unification_table.rollback_to(int_snapshot);
inner.float_unification_table.rollback_to(float_snapshot);
inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot);
inner.region_obligations.truncate(region_obligations_snapshot);
}
fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) {
@ -784,12 +805,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.in_snapshot.set(was_in_snapshot);
self.skip_leak_check.set(was_skip_leak_check);
self.projection_cache.borrow_mut().commit(projection_cache_snapshot);
self.type_variables.borrow_mut().commit(type_snapshot);
self.const_unification_table.borrow_mut().commit(const_snapshot);
self.int_unification_table.borrow_mut().commit(int_snapshot);
self.float_unification_table.borrow_mut().commit(float_snapshot);
self.borrow_region_constraints().commit(region_constraints_snapshot);
let mut inner = self.inner.borrow_mut();
inner.projection_cache.commit(projection_cache_snapshot);
inner.type_variables.commit(type_snapshot);
inner.const_unification_table.commit(const_snapshot);
inner.int_unification_table.commit(int_snapshot);
inner.float_unification_table.commit(float_snapshot);
inner.unwrap_region_constraints().commit(region_constraints_snapshot);
}
/// Executes `f` and commit the bindings.
@ -859,12 +881,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
&self,
snapshot: &CombinedSnapshot<'a, 'tcx>,
) -> Option<bool> {
self.borrow_region_constraints()
self.inner
.borrow_mut()
.unwrap_region_constraints()
.region_constraints_added_in_snapshot(&snapshot.region_constraints_snapshot)
}
pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) {
self.borrow_region_constraints().add_given(sub, sup);
self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup);
}
pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx>
@ -900,7 +924,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
b: ty::Region<'tcx>,
) {
debug!("sub_regions({:?} <: {:?})", a, b);
self.borrow_region_constraints().make_subregion(origin, a, b);
self.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin, a, b);
}
/// Require that the region `r` be equal to one of the regions in
@ -914,7 +938,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
in_regions: &Lrc<Vec<ty::Region<'tcx>>>,
) {
debug!("member_constraint({:?} <: {:?})", region, in_regions);
self.borrow_region_constraints().member_constraint(
self.inner.borrow_mut().unwrap_region_constraints().member_constraint(
opaque_type_def_id,
definition_span,
hidden_ty,
@ -978,7 +1002,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {
self.type_variables.borrow_mut().new_var(self.universe(), diverging, origin)
self.inner.borrow_mut().type_variables.new_var(self.universe(), diverging, origin)
}
pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
@ -990,7 +1014,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
origin: TypeVariableOrigin,
universe: ty::UniverseIndex,
) -> Ty<'tcx> {
let vid = self.type_variables.borrow_mut().new_var(universe, false, origin);
let vid = self.inner.borrow_mut().type_variables.new_var(universe, false, origin);
self.tcx.mk_ty_var(vid)
}
@ -1013,21 +1037,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
universe: ty::UniverseIndex,
) -> &'tcx ty::Const<'tcx> {
let vid = self
.const_unification_table
.inner
.borrow_mut()
.const_unification_table
.new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } });
self.tcx.mk_const_var(vid, ty)
}
pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid<'tcx> {
self.const_unification_table.borrow_mut().new_key(ConstVarValue {
self.inner.borrow_mut().const_unification_table.new_key(ConstVarValue {
origin,
val: ConstVariableValue::Unknown { universe: self.universe() },
})
}
fn next_int_var_id(&self) -> IntVid {
self.int_unification_table.borrow_mut().new_key(None)
self.inner.borrow_mut().int_unification_table.new_key(None)
}
pub fn next_int_var(&self) -> Ty<'tcx> {
@ -1035,7 +1060,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
fn next_float_var_id(&self) -> FloatVid {
self.float_unification_table.borrow_mut().new_key(None)
self.inner.borrow_mut().float_unification_table.new_key(None)
}
pub fn next_float_var(&self) -> Ty<'tcx> {
@ -1057,7 +1082,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
origin: RegionVariableOrigin,
universe: ty::UniverseIndex,
) -> ty::Region<'tcx> {
let region_var = self.borrow_region_constraints().new_region_var(universe, origin);
let region_var =
self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, origin);
self.tcx.mk_region(ty::ReVar(region_var))
}
@ -1067,12 +1093,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
/// placeholders, however, it will return the universe which which
/// they are associated.
fn universe_of_region(&self, r: ty::Region<'tcx>) -> ty::UniverseIndex {
self.borrow_region_constraints().universe(r)
self.inner.borrow_mut().unwrap_region_constraints().universe(r)
}
/// Number of region variables created so far.
pub fn num_region_vars(&self) -> usize {
self.borrow_region_constraints().num_region_vars()
self.inner.borrow_mut().unwrap_region_constraints().num_region_vars()
}
/// Just a convenient wrapper of `next_region_var` for using during NLL.
@ -1105,7 +1131,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// used in a path such as `Foo::<T, U>::new()` will
// use an inference variable for `C` with `[T, U]`
// as the substitutions for the default, `(T, U)`.
let ty_var_id = self.type_variables.borrow_mut().new_var(
let ty_var_id = self.inner.borrow_mut().type_variables.new_var(
self.universe(),
false,
TypeVariableOrigin {
@ -1125,7 +1151,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
span,
};
let const_var_id =
self.const_unification_table.borrow_mut().new_key(ConstVarValue {
self.inner.borrow_mut().const_unification_table.new_key(ConstVarValue {
origin,
val: ConstVariableValue::Unknown { universe: self.universe() },
});
@ -1179,9 +1205,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
suppress: SuppressRegionErrors,
) {
assert!(
self.is_tainted_by_errors() || self.region_obligations.borrow().is_empty(),
self.is_tainted_by_errors() || self.inner.borrow().region_obligations.is_empty(),
"region_obligations not empty: {:#?}",
self.region_obligations.borrow()
self.inner.borrow().region_obligations
);
let region_rels = &RegionRelations::new(
@ -1191,8 +1217,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
outlives_env.free_region_map(),
);
let (var_infos, data) = self
.region_constraints
.inner
.borrow_mut()
.region_constraints
.take()
.expect("regions already resolved")
.into_infos_and_data();
@ -1224,12 +1251,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
/// understands. See the NLL module for mode details.
pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
assert!(
self.region_obligations.borrow().is_empty(),
self.inner.borrow().region_obligations.is_empty(),
"region_obligations not empty: {:#?}",
self.region_obligations.borrow()
self.inner.borrow().region_obligations
);
self.borrow_region_constraints().take_and_reset_data()
self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
}
/// Gives temporary access to the region constraint data.
@ -1238,8 +1265,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
&self,
op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
) -> R {
let region_constraints = self.borrow_region_constraints();
op(region_constraints.data())
let mut inner = self.inner.borrow_mut();
op(inner.unwrap_region_constraints().data())
}
/// Takes ownership of the list of variable regions. This implies
@ -1249,8 +1276,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
/// of the set of region variables into the NLL region context.
pub fn take_region_var_origins(&self) -> VarInfos {
let (var_infos, data) = self
.region_constraints
.inner
.borrow_mut()
.region_constraints
.take()
.expect("regions already resolved")
.into_infos_and_data();
@ -1276,7 +1304,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, ty::UniverseIndex> {
use self::type_variable::TypeVariableValue;
match self.type_variables.borrow_mut().probe(vid) {
match self.inner.borrow_mut().type_variables.probe(vid) {
TypeVariableValue::Known { value } => Ok(value),
TypeVariableValue::Unknown { universe } => Err(universe),
}
@ -1299,7 +1327,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
self.type_variables.borrow_mut().root_var(var)
self.inner.borrow_mut().type_variables.root_var(var)
}
/// Where possible, replaces type/const variables in
@ -1337,7 +1365,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
&self,
vid: ty::ConstVid<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, ty::UniverseIndex> {
match self.const_unification_table.borrow_mut().probe_value(vid).val {
match self.inner.borrow_mut().const_unification_table.probe_value(vid).val {
ConstVariableValue::Known { value } => Ok(value),
ConstVariableValue::Unknown { universe } => Err(universe),
}
@ -1434,7 +1462,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
) {
debug!("verify_generic_bound({:?}, {:?} <: {:?})", kind, a, bound);
self.borrow_region_constraints().verify_generic_bound(origin, kind, a, bound);
self.inner
.borrow_mut()
.unwrap_region_constraints()
.verify_generic_bound(origin, kind, a, bound);
}
pub fn type_is_copy_modulo_regions(
@ -1509,19 +1540,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
InferOk { value, obligations }
}
pub fn borrow_region_constraints(&self) -> RefMut<'_, RegionConstraintCollector<'tcx>> {
RefMut::map(self.region_constraints.borrow_mut(), |c| {
c.as_mut().expect("region constraints already solved")
})
}
/// Clears the selection, evaluation, and projection caches. This is useful when
/// repeatedly attempting to select an `Obligation` while changing only
/// its `ParamEnv`, since `FulfillmentContext` doesn't use probing.
pub fn clear_caches(&self) {
self.selection_cache.clear();
self.evaluation_cache.clear();
self.projection_cache.borrow_mut().clear();
self.inner.borrow_mut().projection_cache.clear();
}
fn universe(&self) -> ty::UniverseIndex {
@ -1562,27 +1587,27 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
// 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)
//
// 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)
}
ty::Infer(ty::IntVar(v)) => self
.infcx
.int_unification_table
.inner
.borrow_mut()
.int_unification_table
.probe_value(v)
.map(|v| v.to_type(self.infcx.tcx))
.unwrap_or(typ),
ty::Infer(ty::FloatVar(v)) => self
.infcx
.float_unification_table
.inner
.borrow_mut()
.float_unification_table
.probe_value(v)
.map(|v| v.to_type(self.infcx.tcx))
.unwrap_or(typ),
@ -1603,7 +1628,7 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
// If `inlined_probe` returns a `Known` value its `kind` never
// matches `infer`.
match self.infcx.type_variables.borrow_mut().inlined_probe(v) {
match self.infcx.inner.borrow_mut().type_variables.inlined_probe(v) {
TypeVariableValue::Unknown { .. } => false,
TypeVariableValue::Known { .. } => true,
}
@ -1613,7 +1638,7 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
// If inlined_probe_value returns a value it's always a
// `ty::Int(_)` or `ty::UInt(_)`, which nevers matches a
// `ty::Infer(_)`.
self.infcx.int_unification_table.borrow_mut().inlined_probe_value(v).is_some()
self.infcx.inner.borrow_mut().int_unification_table.inlined_probe_value(v).is_some()
}
ty::FloatVar(v) => {
@ -1621,7 +1646,7 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
// `ty::Float(_)`, which nevers matches a `ty::Infer(_)`.
//
// Not `inlined_probe_value(v)` because this call site is colder.
self.infcx.float_unification_table.borrow_mut().probe_value(v).is_some()
self.infcx.inner.borrow_mut().float_unification_table.probe_value(v).is_some()
}
_ => unreachable!(),
@ -1641,8 +1666,9 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = ct {
self.infcx
.const_unification_table
.inner
.borrow_mut()
.const_unification_table
.probe_value(*vid)
.val
.known()

View File

@ -322,7 +322,7 @@ where
match value_ty.kind {
ty::Infer(ty::TyVar(value_vid)) => {
// Two type variables: just equate them.
self.infcx.type_variables.borrow_mut().equate(vid, value_vid);
self.infcx.inner.borrow_mut().type_variables.equate(vid, value_vid);
return Ok(value_ty);
}
@ -343,7 +343,7 @@ where
assert!(!generalized_ty.has_infer_types());
}
self.infcx.type_variables.borrow_mut().instantiate(vid, generalized_ty);
self.infcx.inner.borrow_mut().type_variables.instantiate(vid, generalized_ty);
// The generalized values we extract from `canonical_var_values` have
// been fully instantiated and hence the set of scopes we have
@ -373,7 +373,7 @@ where
delegate: &mut self.delegate,
first_free_index: ty::INNERMOST,
ambient_variance: self.ambient_variance,
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),
universe,
};
@ -870,7 +870,7 @@ where
}
ty::Infer(ty::TyVar(vid)) => {
let mut variables = self.infcx.type_variables.borrow_mut();
let variables = &mut self.infcx.inner.borrow_mut().type_variables;
let vid = variables.root_var(vid);
let sub_vid = variables.sub_root_var(vid);
if sub_vid == self.for_vid_sub_root {
@ -972,7 +972,7 @@ where
bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
}
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.known() {
Some(u) => self.relate(&u, &u),

View File

@ -82,7 +82,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
) {
debug!("register_region_obligation(body_id={:?}, obligation={:?})", body_id, obligation);
self.region_obligations.borrow_mut().push((body_id, obligation));
self.inner.borrow_mut().region_obligations.push((body_id, obligation));
}
pub fn register_region_obligation_with_cause(
@ -103,7 +103,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
/// Trait queries just want to pass back type obligations "as is"
pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionObligation<'tcx>)> {
::std::mem::take(&mut *self.region_obligations.borrow_mut())
::std::mem::take(&mut self.inner.borrow_mut().region_obligations)
}
/// Process the region obligations that must be proven (during

View File

@ -75,9 +75,12 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticTypeAndRegionResolver<'a, 'tcx>
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
ty::ReVar(rid) => {
self.infcx.borrow_region_constraints().opportunistic_resolve_var(self.tcx(), rid)
}
ty::ReVar(rid) => self
.infcx
.inner
.borrow_mut()
.unwrap_region_constraints()
.opportunistic_resolve_var(self.tcx(), rid),
_ => r,
}
}
@ -120,7 +123,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
// Since we called `shallow_resolve` above, this must
// be an (as yet...) unresolved inference variable.
let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty {
let ty_vars = self.infcx.type_variables.borrow();
let ty_vars = &self.infcx.inner.borrow().type_variables;
if let TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
span,

View File

@ -80,8 +80,8 @@ impl TypeRelation<'tcx> for Sub<'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);
match (&a.kind, &b.kind) {
(&ty::Infer(TyVar(a_vid)), &ty::Infer(TyVar(b_vid))) => {
// Shouldn't have any LBR here, so we can safely put
@ -95,7 +95,7 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> {
// have to record in the `type_variables` tracker that
// the two variables are equal modulo subtyping, which
// is important to the occurs check later on.
infcx.type_variables.borrow_mut().sub(a_vid, b_vid);
infcx.inner.borrow_mut().type_variables.sub(a_vid, b_vid);
self.fields.obligations.push(Obligation::new(
self.fields.trace.cause.clone(),
self.fields.param_env,
@ -140,7 +140,12 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> {
// from the "cause" field, we could perhaps give more tailored
// error messages.
let origin = SubregionOrigin::Subtype(box self.fields.trace.clone());
self.fields.infcx.borrow_region_constraints().make_subregion(origin, a, b);
self.fields
.infcx
.inner
.borrow_mut()
.unwrap_region_constraints()
.make_subregion(origin, a, b);
Ok(a)
}

View File

@ -4,7 +4,6 @@ use rustc_data_structures::unify::{EqUnifyValue, NoError, UnificationTable, Unif
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use std::cell::RefMut;
use std::cmp;
use std::marker::PhantomData;
@ -214,7 +213,7 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
impl<'tcx> EqUnifyValue for &'tcx ty::Const<'tcx> {}
pub fn replace_if_possible(
mut table: RefMut<'_, UnificationTable<InPlace<ty::ConstVid<'tcx>>>>,
table: &mut UnificationTable<InPlace<ty::ConstVid<'tcx>>>,
c: &'tcx ty::Const<'tcx>,
) -> &'tcx ty::Const<'tcx> {
if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = c {

View File

@ -199,12 +199,22 @@ impl<'tcx> AutoTraitFinder<'tcx> {
panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, e)
});
let body_id_map: FxHashMap<_, _> =
infcx.region_obligations.borrow().iter().map(|&(id, _)| (id, vec![])).collect();
let body_id_map: FxHashMap<_, _> = infcx
.inner
.borrow()
.region_obligations
.iter()
.map(|&(id, _)| (id, vec![]))
.collect();
infcx.process_registered_region_obligations(&body_id_map, None, full_env);
let region_data = infcx.borrow_region_constraints().region_constraint_data().clone();
let region_data = infcx
.inner
.borrow_mut()
.unwrap_region_constraints()
.region_constraint_data()
.clone();
let vid_to_region = self.map_vid_to_region(&region_data);

View File

@ -486,7 +486,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
// bounds. It might be the case that we want two distinct caches,
// or else another kind of cache entry.
let cache_result = infcx.projection_cache.borrow_mut().try_start(cache_key);
let cache_result = infcx.inner.borrow_mut().projection_cache.try_start(cache_key);
match cache_result {
Ok(()) => {}
Err(ProjectionCacheEntry::Ambiguous) => {
@ -560,7 +560,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
// Once we have inferred everything we need to know, we
// can ignore the `obligations` from that point on.
if infcx.unresolved_type_vars(&ty.value).is_none() {
infcx.projection_cache.borrow_mut().complete_normalized(cache_key, &ty);
infcx.inner.borrow_mut().projection_cache.complete_normalized(cache_key, &ty);
// No need to extend `obligations`.
} else {
obligations.extend(ty.obligations);
@ -627,7 +627,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
};
let cache_value = prune_cache_value_obligations(infcx, &result);
infcx.projection_cache.borrow_mut().insert_ty(cache_key, cache_value);
infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, cache_value);
obligations.extend(result.obligations);
Some(result.value)
}
@ -638,7 +638,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
projected_ty
);
let result = Normalized { value: projected_ty, obligations: vec![] };
infcx.projection_cache.borrow_mut().insert_ty(cache_key, result.clone());
infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, result.clone());
// No need to extend `obligations`.
Some(result.value)
}
@ -647,7 +647,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
"opt_normalize_projection_type: \
too many candidates"
);
infcx.projection_cache.borrow_mut().ambiguous(cache_key);
infcx.inner.borrow_mut().projection_cache.ambiguous(cache_key);
None
}
Err(ProjectionTyError::TraitSelectionError(_)) => {
@ -657,7 +657,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
// Trait`, which when processed will cause the error to be
// reported later
infcx.projection_cache.borrow_mut().error(cache_key);
infcx.inner.borrow_mut().projection_cache.error(cache_key);
let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
obligations.extend(result.obligations);
Some(result.value)

View File

@ -513,7 +513,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if let Some(key) =
ProjectionCacheKey::from_poly_projection_predicate(self, data)
{
self.infcx.projection_cache.borrow_mut().complete(key);
self.infcx.inner.borrow_mut().projection_cache.complete(key);
}
result
}

View File

@ -226,7 +226,9 @@ impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> {
let b = match b {
&ty::ReVar(vid) => self
.infcx
.borrow_region_constraints()
.inner
.borrow_mut()
.unwrap_region_constraints()
.opportunistic_resolve_var(self.infcx.tcx, vid),
other => other,