From 7426853ba255940b880f2e7f8026d60b94b42404 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 Jan 2020 08:45:57 +1100 Subject: [PATCH] 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. --- src/librustc/infer/canonical/canonicalizer.rs | 6 +- src/librustc/infer/combine.rs | 50 +-- src/librustc/infer/equate.rs | 13 +- .../infer/error_reporting/need_type_info.rs | 13 +- src/librustc/infer/freshen.rs | 18 +- src/librustc/infer/fudge.rs | 32 +- src/librustc/infer/glb.rs | 7 +- src/librustc/infer/higher_ranked/mod.rs | 2 +- src/librustc/infer/lattice.rs | 4 +- src/librustc/infer/lub.rs | 7 +- src/librustc/infer/mod.rs | 336 ++++++++++-------- src/librustc/infer/nll_relate/mod.rs | 10 +- src/librustc/infer/outlives/obligations.rs | 4 +- src/librustc/infer/resolve.rs | 11 +- src/librustc/infer/sub.rs | 13 +- src/librustc/infer/unify_key.rs | 3 +- src/librustc/traits/auto_trait.rs | 16 +- src/librustc/traits/project.rs | 12 +- src/librustc/traits/select.rs | 2 +- .../chalk_context/resolvent_ops.rs | 4 +- 20 files changed, 321 insertions(+), 242 deletions(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 48a6c6d7413..85fafa34915 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -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`) diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 2518805a1ec..9eb961255c2 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -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), diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index f192295c1aa..018bbe03543 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -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) } diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 9947dea2340..0d7fce7eac6 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -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, ) -> (String, Option, Cow<'static, str>, Option, 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 { diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index cf61cac0ac4..0190989267b 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -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), diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index 265e45635cf..d0b7bb32b98 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -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>>>, + table: &mut ut::UnificationTable>>, snapshot: &ut::Snapshot>>, ) -> (Range>, Vec) { 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 } } diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs index 293dc80d983..6ef92132bc7 100644 --- a/src/librustc/infer/glb.rs +++ b/src/librustc/infer/glb.rs @@ -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( diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index d25d186f4d7..1b0f399ca33 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -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, diff --git a/src/librustc/infer/lattice.rs b/src/librustc/infer/lattice.rs index 3e0aa4727ae..df475af1151 100644 --- a/src/librustc/infer/lattice.rs +++ b/src/librustc/infer/lattice.rs @@ -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 diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs index b512d3df3e8..6a699f803c7 100644 --- a/src/librustc/infer/lub.rs +++ b/src/librustc/infer/lub.rs @@ -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( diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index b93f4408cdc..be58de996a5 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -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` 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>>, + + /// Map from integral variable to the kind of integer it represents. + int_unification_table: ut::UnificationTable>, + + /// Map from floating variable to the kind of float it represents. + float_unification_table: ut::UnificationTable>, + + /// 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>, + + /// 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 { ... } + /// + /// 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>>, - /// Cache for projections. This cache is snapshotted along with the - /// infcx. - /// - /// Public so that `traits::project` can use it. - pub projection_cache: RefCell>, - - /// We instantiate `UnificationTable` with `bounds` because the - /// types that might instantiate a general type variable have an - /// order, represented by its upper and lower bounds. - pub type_variables: RefCell>, + pub inner: RefCell>, /// 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, - /// Map from const parameter variable to the kind of const it represents. - const_unification_table: RefCell>>>, - - /// Map from integral variable to the kind of integer it represents. - int_unification_table: RefCell>>, - - /// Map from floating variable to the kind of float it represents - float_unification_table: RefCell>>, - - /// 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>>, - /// Once region inference is done, the values for each variable. lexical_region_resolutions: RefCell>>, @@ -189,39 +247,6 @@ pub struct InferCtxt<'a, 'tcx> { /// This flag is true while there is an active snapshot. in_snapshot: Cell, - /// 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 { ... } - /// - /// 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)>>, - /// 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> { - 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> = 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 { - 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(&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>>, ) { 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::::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::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() diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index 6af004f7776..77e20e6ad8f 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -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), diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index 45e4a84589e..17153ef9724 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -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 diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs index d7dc6070442..c9acd1cf4a1 100644 --- a/src/librustc/infer/resolve.rs +++ b/src/librustc/infer/resolve.rs @@ -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, diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index f355ffe1962..ef4903358d5 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -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) } diff --git a/src/librustc/infer/unify_key.rs b/src/librustc/infer/unify_key.rs index d88188538fc..e205453a48c 100644 --- a/src/librustc/infer/unify_key.rs +++ b/src/librustc/infer/unify_key.rs @@ -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>>>, + table: &mut UnificationTable>>, c: &'tcx ty::Const<'tcx>, ) -> &'tcx ty::Const<'tcx> { if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = c { diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index d775393a808..1255728de37 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -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(®ion_data); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index fffcf66075f..6c058455b98 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -454,7 +454,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) => { @@ -528,7 +528,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); @@ -590,7 +590,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) } @@ -601,7 +601,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) } @@ -610,7 +610,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(_)) => { @@ -620,7 +620,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) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index e4ef68c167f..c56cde4f4ce 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -511,7 +511,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 } diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs index 301ebf8adc5..dc6018e80ea 100644 --- a/src/librustc_traits/chalk_context/resolvent_ops.rs +++ b/src/librustc_traits/chalk_context/resolvent_ops.rs @@ -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,