diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 48a6c6d7413d1..85fafa349151e 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 2518805a1ecfc..9eb961255c295 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 f192295c1aa07..018bbe035431e 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 9947dea234096..0d7fce7eac6c5 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 cf61cac0ac4bb..0190989267bb4 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 265e45635cf53..d0b7bb32b9815 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 293dc80d983a9..6ef92132bc703 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 d25d186f4d74e..1b0f399ca3392 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 3e0aa4727ae1a..df475af1151aa 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 b512d3df3e8df..6a699f803c7b8 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 b93f4408cdc46..02b464fd5abbb 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,25 +105,18 @@ impl SuppressRegionErrors { } } -pub struct InferCtxt<'a, 'tcx> { - pub tcx: TyCtxt<'tcx>, - - /// During type-checking/inference of a body, `in_progress_tables` - /// contains a reference to the tables being built up, which are - /// used for reading closure kinds/signatures as they are inferred, - /// 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. +/// This type contains all the things within `InferCtxt` that sit within a +/// `RefCell`. +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: RefCell>, + 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. - pub type_variables: 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. + type_variables: type_variable::TypeVariableTable<'tcx>, /// If set, this flag causes us to skip the 'leak check' during /// higher-ranked subtyping operations. This flag is a temporary one used @@ -133,20 +126,83 @@ pub struct InferCtxt<'a, 'tcx> { skip_leak_check: Cell, /// Map from const parameter variable to the kind of const it represents. - const_unification_table: RefCell>>>, + const_unification_table: ut::UnificationTable>>, /// Map from integral variable to the kind of integer it represents. - int_unification_table: RefCell>>, + 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>, - /// Map from floating variable to the kind of float it represents - float_unification_table: RefCell>>, + /// During type-checking/inference of a body, `in_progress_tables` + /// contains a reference to the tables being built up, which are + /// used for reading closure kinds/signatures as they are inferred, + /// and for error reporting logic to read arbitrary node types. + pub in_progress_tables: Option<&'a 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>>, + pub inner: RefCell>, /// Once region inference is done, the values for each variable. lexical_region_resolutions: RefCell>>, @@ -189,39 +245,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 +566,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(), @@ -616,7 +634,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 +648,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 +666,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 +737,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 +775,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 +804,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 +880,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 +923,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 +937,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 +1001,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 +1013,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 +1036,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 +1059,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 +1081,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 +1092,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 +1130,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 +1150,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 +1204,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 +1216,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 +1250,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 +1264,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 +1275,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 +1303,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 +1326,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 +1364,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 +1461,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 +1539,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 +1586,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 +1627,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 +1637,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 +1645,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 +1665,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 6af004f7776a1..77e20e6ad8ff2 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 45e4a84589eb5..17153ef97241b 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 d7dc607044222..c9acd1cf4a1b3 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 f355ffe196202..ef4903358d5c9 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 d88188538fccb..e205453a48c53 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/query/mod.rs b/src/librustc/query/mod.rs index d1bccb961c48b..7cb1f3aa0e851 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -323,7 +323,7 @@ rustc_queries! { query associated_item(_: DefId) -> ty::AssocItem {} /// Collects the associated items defined on a trait or impl. - query associated_items(key: DefId) -> ty::AssocItemsIterator<'tcx> { + query associated_items(key: DefId) -> &'tcx [ty::AssocItem] { desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) } } diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index d775393a808f7..1255728de37b1 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/mod.rs b/src/librustc/traits/mod.rs index 25bb54033f165..783807b5c3b59 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -541,6 +541,7 @@ fn vtable_methods<'tcx>( tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| { let trait_methods = tcx .associated_items(trait_ref.def_id()) + .iter() .filter(|item| item.kind == ty::AssocKind::Method); // Now list each method's DefId and InternalSubsts (for within its trait). diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index d0dbfe73c91d5..3c886ce7f3eb7 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -212,6 +212,7 @@ fn object_safety_violations_for_trait( // Check methods for violations. let mut violations: Vec<_> = tcx .associated_items(trait_def_id) + .iter() .filter(|item| item.kind == ty::AssocKind::Method) .filter_map(|item| { object_safety_violation_for_method(tcx, trait_def_id, &item) @@ -277,6 +278,7 @@ fn object_safety_violations_for_trait( violations.extend( tcx.associated_items(trait_def_id) + .iter() .filter(|item| item.kind == ty::AssocKind::Const) .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)), ); @@ -632,7 +634,9 @@ fn object_ty_for_trait<'tcx>( let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref)) .flat_map(|super_trait_ref| { - tcx.associated_items(super_trait_ref.def_id()).map(move |item| (super_trait_ref, item)) + tcx.associated_items(super_trait_ref.def_id()) + .iter() + .map(move |item| (super_trait_ref, item)) }) .filter(|(_, item)| item.kind == ty::AssocKind::Type) .collect::>(); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index a1d785cf4447a..5d9f4ddfd167e 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -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) @@ -1473,7 +1473,7 @@ fn assoc_ty_def( { return specialization_graph::NodeItem { node: specialization_graph::Node::Impl(impl_def_id), - item, + item: *item, }; } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 26f2a4ddb385a..f298d150c6f56 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -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 } diff --git a/src/librustc/traits/types/specialization_graph.rs b/src/librustc/traits/types/specialization_graph.rs index 3086850db6d9c..36a84369d4a3a 100644 --- a/src/librustc/traits/types/specialization_graph.rs +++ b/src/librustc/traits/types/specialization_graph.rs @@ -81,7 +81,7 @@ impl<'tcx> Node { } /// Iterate over the items defined directly by the given (impl or trait) node. - pub fn items(&self, tcx: TyCtxt<'tcx>) -> ty::AssocItemsIterator<'tcx> { + pub fn items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ty::AssocItem] { tcx.associated_items(self.def_id()) } @@ -98,8 +98,10 @@ impl<'tcx> Node { ) -> Option { use crate::ty::AssocKind::*; - tcx.associated_items(self.def_id()).find(move |impl_item| { - match (trait_item_kind, impl_item.kind) { + tcx.associated_items(self.def_id()) + .iter() + .find(move |impl_item| { + match (trait_item_kind, impl_item.kind) { | (Const, Const) | (Method, Method) | (Type, Type) @@ -112,7 +114,8 @@ impl<'tcx> Node { | (OpaqueTy, _) => false, } - }) + }) + .copied() } pub fn def_id(&self) -> DefId { diff --git a/src/librustc/traits/wf.rs b/src/librustc/traits/wf.rs index fbcb77a403183..1c47b5353160d 100644 --- a/src/librustc/traits/wf.rs +++ b/src/librustc/traits/wf.rs @@ -166,7 +166,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let extend_cause_with_original_assoc_item_obligation = |cause: &mut traits::ObligationCause<'_>, pred: &ty::Predicate<'_>, - trait_assoc_items: ty::AssocItemsIterator<'_>| { + trait_assoc_items: &[ty::AssocItem]| { let trait_item = tcx .hir() .as_local_hir_id(trait_ref.def_id) @@ -283,6 +283,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind)) { if let Some((impl_item, trait_assoc_item)) = trait_assoc_items + .iter() .filter(|i| i.def_id == *item_def_id) .next() .and_then(|trait_assoc_item| { @@ -325,7 +326,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { extend_cause_with_original_assoc_item_obligation( &mut cause, &pred, - trait_assoc_items.clone(), + trait_assoc_items, ); traits::Obligation::new(cause, param_env, pred) }); diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index db034d1618cea..f4006a1cd40c1 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -122,6 +122,7 @@ impl<'tcx> OverloadedDeref<'tcx> { }; let method_def_id = tcx .associated_items(trait_def_id.unwrap()) + .iter() .find(|m| m.kind == ty::AssocKind::Method) .unwrap() .def_id; diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 51a18f8eae274..c7f19513f666e 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -376,6 +376,7 @@ impl<'tcx> Instance<'tcx> { let fn_once = tcx.lang_items().fn_once_trait().unwrap(); let call_once = tcx .associated_items(fn_once) + .iter() .find(|it| it.kind == ty::AssocKind::Method) .unwrap() .def_id; diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2538322431ec9..0118fc4c8ac84 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2705,14 +2705,14 @@ impl<'tcx> TyCtxt<'tcx> { .for_each(|&body_id| f(self.hir().body_owner_def_id(body_id))); } - pub fn provided_trait_methods(self, id: DefId) -> Vec { + pub fn provided_trait_methods(self, id: DefId) -> impl Iterator { self.associated_items(id) + .iter() .filter(|item| item.kind == AssocKind::Method && item.defaultness.has_value()) - .collect() } pub fn trait_relevant_for_never(self, did: DefId) -> bool { - self.associated_items(did).any(|item| item.relevant_for_never()) + self.associated_items(did).iter().any(|item| item.relevant_for_never()) } pub fn opt_item_name(self, def_id: DefId) -> Option { @@ -2974,25 +2974,6 @@ impl<'tcx> TyCtxt<'tcx> { } } -#[derive(Copy, Clone, HashStable)] -pub struct AssocItemsIterator<'tcx> { - pub items: &'tcx [AssocItem], -} - -impl<'tcx> Iterator for AssocItemsIterator<'tcx> { - type Item = AssocItem; - - #[inline] - fn next(&mut self) -> Option { - if let Some((first, rest)) = self.items.split_first() { - self.items = rest; - Some(*first) - } else { - None - } - } -} - #[derive(Clone, HashStable)] pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]); diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 4c5bc3debde54..0718853b1df59 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1066,6 +1066,7 @@ impl<'tcx> ProjectionTy<'tcx> { ) -> ProjectionTy<'tcx> { let item_def_id = tcx .associated_items(trait_ref.def_id) + .iter() .find(|item| { item.kind == ty::AssocKind::Type && tcx.hygienic_eq(item_name, item.ident, trait_ref.def_id) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 4dfff85d53147..5d5fa4090c800 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -355,7 +355,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut dtor_did = None; let ty = self.type_of(adt_did); self.for_each_relevant_impl(drop_trait, ty, |impl_did| { - if let Some(item) = self.associated_items(impl_did).next() { + if let Some(item) = self.associated_items(impl_did).first() { if validate(self, impl_did).is_ok() { dtor_did = Some(item.def_id); } diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index d9077d1606f3a..78bf149f0e01a 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1074,12 +1074,15 @@ impl<'a> State<'a> { fn print_associated_type( &mut self, ident: ast::Ident, + generics: &ast::Generics, bounds: &ast::GenericBounds, ty: Option<&ast::Ty>, ) { self.word_space("type"); self.print_ident(ident); + self.print_generic_params(&generics.params); self.print_type_bounds(":", bounds); + self.print_where_clause(&generics.where_clause); if let Some(ty) = ty { self.s.space(); self.word_space("="); @@ -1474,7 +1477,7 @@ impl<'a> State<'a> { self.print_fn_full(sig, item.ident, &item.generics, &item.vis, body, &item.attrs); } ast::AssocItemKind::TyAlias(bounds, ty) => { - self.print_associated_type(item.ident, bounds, ty.as_deref()); + self.print_associated_type(item.ident, &item.generics, bounds, ty.as_deref()); } ast::AssocItemKind::Macro(mac) => { self.print_mac(mac); diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index c1a7bb5087824..22effb102fd67 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -559,7 +559,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { file_metadata, loc.line as c_uint, type_metadata, - self.sess().opts.optimize != config::OptLevel::No, + true, DIFlags::FlagZero, argument_index, align.bytes() as u32, diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs index b0d2f96c71a03..071c3de4b1c2c 100644 --- a/src/librustc_hir/print.rs +++ b/src/librustc_hir/print.rs @@ -454,14 +454,17 @@ impl<'a> State<'a> { fn print_associated_type( &mut self, ident: ast::Ident, + generics: &hir::Generics<'_>, bounds: Option>, ty: Option<&hir::Ty<'_>>, ) { self.word_space("type"); self.print_ident(ident); + self.print_generic_params(&generics.params); if let Some(bounds) = bounds { self.print_bounds(":", bounds); } + self.print_where_clause(&generics.where_clause); if let Some(ty) = ty { self.s.space(); self.word_space("="); @@ -902,6 +905,7 @@ impl<'a> State<'a> { hir::TraitItemKind::Type(ref bounds, ref default) => { self.print_associated_type( ti.ident, + &ti.generics, Some(bounds), default.as_ref().map(|ty| &**ty), ); @@ -930,7 +934,7 @@ impl<'a> State<'a> { self.ann.nested(self, Nested::Body(body)); } hir::ImplItemKind::TyAlias(ref ty) => { - self.print_associated_type(ii.ident, None, Some(ty)); + self.print_associated_type(ii.ident, &ii.generics, None, Some(ty)); } hir::ImplItemKind::OpaqueTy(bounds) => { self.word_space("type"); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 94a5f2b3bf86d..a8c66be359c4a 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -68,6 +68,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx let fn_mut = tcx.lang_items().fn_mut_trait().unwrap(); let call_mut = tcx .associated_items(fn_mut) + .iter() .find(|it| it.kind == ty::AssocKind::Method) .unwrap() .def_id; diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 1be3da4b3d85a..091ae1bbb799d 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -539,7 +539,7 @@ where debug!("destructor_call_block({:?}, {:?})", self, succ); let tcx = self.tcx(); let drop_trait = tcx.lang_items().drop_trait().unwrap(); - let drop_fn = tcx.associated_items(drop_trait).next().unwrap(); + let drop_fn = tcx.associated_items(drop_trait)[0]; let ty = self.place_ty(self.place); let substs = tcx.mk_substs_trait(ty, &[]); diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index 667898046ac36..888f4370dd5e8 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -362,12 +362,12 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx return; } - let provided_trait_methods = self.tcx.provided_trait_methods(trait_def_id); - self.worklist.reserve(provided_trait_methods.len()); - for default_method in provided_trait_methods { - let hir_id = self.tcx.hir().as_local_hir_id(default_method.def_id).unwrap(); - self.worklist.push(hir_id); - } + // FIXME(#53488) remove `let` + let tcx = self.tcx; + self.worklist.extend( + tcx.provided_trait_methods(trait_def_id) + .map(|assoc| tcx.hir().as_local_hir_id(assoc.def_id).unwrap()), + ); } } } diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 4009cc6d725ab..12debfb66a431 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -468,6 +468,7 @@ impl Visitor<'tcx> for Checker<'tcx> { let trait_item_def_id = self .tcx .associated_items(trait_did) + .iter() .find(|item| item.ident.name == impl_item.ident.name) .map(|item| item.def_id); if let Some(def_id) = trait_item_def_id { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index e32f47443667b..401e172275113 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -423,6 +423,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { qualname.push_str(&self.tcx.def_path_str(def_id)); self.tcx .associated_items(def_id) + .iter() .find(|item| item.ident.name == ident.name) .map(|item| decl_id = Some(item.def_id)); } @@ -717,6 +718,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { let ti = self.tcx.associated_item(decl_id); self.tcx .associated_items(ti.container.id()) + .iter() .find(|item| { item.ident.name == ti.ident.name && item.defaultness.has_value() }) diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs index 301ebf8adc5c7..dc6018e80ea7e 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, diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index aa05165e3de32..b032acf82f582 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -206,12 +206,10 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { } } -fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AssocItemsIterator<'tcx> { - ty::AssocItemsIterator { - items: tcx.arena.alloc_from_iter( - tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)), - ), - } +fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [ty::AssocItem] { + tcx.arena.alloc_from_iter( + tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)), + ) } fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 6bd120d818d09..2909d0f8c54e7 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1109,7 +1109,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_def_id: DefId, assoc_name: ast::Ident, ) -> bool { - self.tcx().associated_items(trait_def_id).any(|item| { + self.tcx().associated_items(trait_def_id).iter().any(|item| { item.kind == ty::AssocKind::Type && self.tcx().hygienic_eq(assoc_name, item.ident, trait_def_id) }) @@ -1347,6 +1347,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id); let assoc_ty = tcx .associated_items(candidate.def_id()) + .iter() .find(|i| i.kind == ty::AssocKind::Type && i.ident.modern() == assoc_ident) .expect("missing associated type"); @@ -1512,6 +1513,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::Predicate::Trait(pred, _) => { associated_types.entry(span).or_default().extend( tcx.associated_items(pred.def_id()) + .iter() .filter(|item| item.kind == ty::AssocKind::Type) .map(|item| item.def_id), ); @@ -1969,6 +1971,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let bound_span = self .tcx() .associated_items(bound.def_id()) + .iter() .find(|item| { item.kind == ty::AssocKind::Type && self.tcx().hygienic_eq(assoc_name, item.ident, bound.def_id()) @@ -2198,6 +2201,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id); let item = tcx .associated_items(trait_did) + .iter() .find(|i| Namespace::from(i.kind) == Namespace::Type && i.ident.modern() == assoc_ident) .expect("missing associated type"); diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 26777b3b01048..707125b3fd522 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -248,7 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if is_gen { // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return` // associated item and not yield. - let return_assoc_item = self.tcx.associated_items(gen_trait).nth(1).unwrap().def_id; + let return_assoc_item = self.tcx.associated_items(gen_trait)[1].def_id; if return_assoc_item != projection.projection_def_id() { debug!("deduce_sig_from_projection: not return assoc item of generator"); return None; @@ -673,7 +673,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The `Future` trait has only one associted item, `Output`, // so check that this is what we see. - let output_assoc_item = self.tcx.associated_items(future_trait).nth(0).unwrap().def_id; + let output_assoc_item = self.tcx.associated_items(future_trait)[0].def_id; if output_assoc_item != predicate.projection_ty.item_def_id { span_bug!( cause_span, diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index e0f9fcc69325c..8c7f1330820e3 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -536,6 +536,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let item_def_id = self .tcx .associated_items(deref_trait) + .iter() .find(|item| item.kind == ty::AssocKind::Type) .unwrap() .def_id; diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index e90c2ef5e4361..67d8030a9d69b 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -474,8 +474,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name: ast::Ident, ns: Namespace, ) -> Option { - self.tcx.associated_items(def_id).find(|item| { - Namespace::from(item.kind) == ns && self.tcx.hygienic_eq(item_name, item.ident, def_id) - }) + self.tcx + .associated_items(def_id) + .iter() + .find(|item| { + Namespace::from(item.kind) == ns + && self.tcx.hygienic_eq(item_name, item.ident, def_id) + }) + .copied() } } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 2444fc60f77ba..497a401a031e5 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1696,10 +1696,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let max_dist = max(name.as_str().len(), 3) / 3; self.tcx .associated_items(def_id) + .iter() .filter(|x| { let dist = lev_distance(&*name.as_str(), &x.ident.as_str()); Namespace::from(x.kind) == Namespace::Value && dist > 0 && dist <= max_dist }) + .copied() .collect() } else { self.fcx @@ -1707,7 +1709,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .map_or(Vec::new(), |x| vec![x]) } } else { - self.tcx.associated_items(def_id).collect() + self.tcx.associated_items(def_id).to_vec() } } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 15cf05a7f7f40..f7cba1521cb06 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1976,6 +1976,7 @@ fn check_impl_items_against_trait<'tcx>( let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id)); let ty_trait_item = tcx .associated_items(impl_trait_ref.def_id) + .iter() .find(|ac| { Namespace::from(&impl_item.kind) == Namespace::from(ac.kind) && tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id) @@ -1983,6 +1984,7 @@ fn check_impl_items_against_trait<'tcx>( .or_else(|| { // Not compatible, but needed for the error message tcx.associated_items(impl_trait_ref.def_id) + .iter() .find(|ac| tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id)) }); @@ -2096,7 +2098,7 @@ fn check_impl_items_against_trait<'tcx>( if !is_implemented && !traits::impl_is_default(tcx, impl_id) { if !trait_item.defaultness.has_value() { - missing_items.push(trait_item); + missing_items.push(*trait_item); } else if associated_type_overridden { invalidated_items.push(trait_item.ident); } @@ -5175,7 +5177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Check for `Future` implementations by constructing a predicate to // prove: `::Output == U` let future_trait = self.tcx.lang_items().future_trait().unwrap(); - let item_def_id = self.tcx.associated_items(future_trait).next().unwrap().def_id; + let item_def_id = self.tcx.associated_items(future_trait)[0].def_id; let predicate = ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate { // `::Output` diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index 3e17b661cf4ce..fb9c173f52000 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -1,6 +1,6 @@ use crate::namespace::Namespace; use rustc::traits::{self, IntercrateMode, SkipLeakCheck}; -use rustc::ty::TyCtxt; +use rustc::ty::{AssocItem, TyCtxt}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; @@ -17,38 +17,60 @@ struct InherentOverlapChecker<'tcx> { } impl InherentOverlapChecker<'tcx> { + /// Checks whether any associated items in impls 1 and 2 share the same identifier and + /// namespace. + fn impls_have_common_items(&self, impl1: DefId, impl2: DefId) -> bool { + let impl_items1 = self.tcx.associated_items(impl1); + let impl_items2 = self.tcx.associated_items(impl2); + + for item1 in &impl_items1[..] { + for item2 in &impl_items2[..] { + // Avoid costly `.modern()` calls as much as possible by doing them as late as we + // can. Compare raw symbols first. + if item1.ident.name == item2.ident.name + && Namespace::from(item1.kind) == Namespace::from(item2.kind) + { + // Symbols and namespace match, compare hygienically. + if item1.ident.modern() == item2.ident.modern() { + return true; + } + } + } + } + + false + } + fn check_for_common_items_in_impls( &self, impl1: DefId, impl2: DefId, overlap: traits::OverlapResult<'_>, ) { - let name_and_namespace = |def_id| { - let item = self.tcx.associated_item(def_id); - (item.ident.modern(), Namespace::from(item.kind)) - }; + let name_and_namespace = + |assoc: &AssocItem| (assoc.ident.modern(), Namespace::from(assoc.kind)); - let impl_items1 = self.tcx.associated_item_def_ids(impl1); - let impl_items2 = self.tcx.associated_item_def_ids(impl2); + let impl_items1 = self.tcx.associated_items(impl1); + let impl_items2 = self.tcx.associated_items(impl2); - for &item1 in &impl_items1[..] { + for item1 in &impl_items1[..] { let (name, namespace) = name_and_namespace(item1); - for &item2 in &impl_items2[..] { + for item2 in &impl_items2[..] { if (name, namespace) == name_and_namespace(item2) { let mut err = struct_span_err!( self.tcx.sess, - self.tcx.span_of_impl(item1).unwrap(), + self.tcx.span_of_impl(item1.def_id).unwrap(), E0592, "duplicate definitions with name `{}`", name ); err.span_label( - self.tcx.span_of_impl(item1).unwrap(), + self.tcx.span_of_impl(item1.def_id).unwrap(), format!("duplicate definitions for `{}`", name), ); err.span_label( - self.tcx.span_of_impl(item2).unwrap(), + self.tcx.span_of_impl(item2.def_id).unwrap(), format!("other definition for `{}`", name), ); @@ -66,27 +88,21 @@ impl InherentOverlapChecker<'tcx> { } } - fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) { - let impls = self.tcx.inherent_impls(ty_def_id); - - for (i, &impl1_def_id) in impls.iter().enumerate() { - for &impl2_def_id in &impls[(i + 1)..] { - traits::overlapping_impls( - self.tcx, - impl1_def_id, - impl2_def_id, - IntercrateMode::Issue43355, - // We go ahead and just skip the leak check for - // inherent impls without warning. - SkipLeakCheck::Yes, - |overlap| { - self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap); - false - }, - || true, - ); - } - } + fn check_for_overlapping_inherent_impls(&self, impl1_def_id: DefId, impl2_def_id: DefId) { + traits::overlapping_impls( + self.tcx, + impl1_def_id, + impl2_def_id, + IntercrateMode::Issue43355, + // We go ahead and just skip the leak check for + // inherent impls without warning. + SkipLeakCheck::Yes, + |overlap| { + self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap); + false + }, + || true, + ); } } @@ -97,8 +113,16 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> { | hir::ItemKind::Struct(..) | hir::ItemKind::Trait(..) | hir::ItemKind::Union(..) => { - let type_def_id = self.tcx.hir().local_def_id(item.hir_id); - self.check_for_overlapping_inherent_impls(type_def_id); + let ty_def_id = self.tcx.hir().local_def_id(item.hir_id); + let impls = self.tcx.inherent_impls(ty_def_id); + + for (i, &impl1_def_id) in impls.iter().enumerate() { + for &impl2_def_id in &impls[(i + 1)..] { + if self.impls_have_common_items(impl1_def_id, impl2_def_id) { + self.check_for_overlapping_inherent_impls(impl1_def_id, impl2_def_id); + } + } + } } _ => {} } diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 18ebd254507ea..288446b6219ce 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -87,7 +87,6 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .cx .tcx .provided_trait_methods(trait_def_id) - .into_iter() .map(|meth| meth.ident.to_string()) .collect(); @@ -115,6 +114,8 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .cx .tcx .associated_items(impl_def_id) + .iter() + .copied() .collect::>() .clean(self.cx), polarity: None, diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index df72bf0b56e61..90ce8802f6584 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -191,7 +191,7 @@ pub fn record_extern_fqn(cx: &DocContext<'_>, did: DefId, kind: clean::TypeKind) pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait { let auto_trait = cx.tcx.trait_def(did).has_auto_impl; - let trait_items = cx.tcx.associated_items(did).map(|item| item.clean(cx)).collect(); + let trait_items = cx.tcx.associated_items(did).iter().map(|item| item.clean(cx)).collect(); let predicates = cx.tcx.predicates_of(did); let generics = (cx.tcx.generics_of(did), predicates).clean(cx); let generics = filter_non_trait_generics(did, generics); @@ -376,6 +376,7 @@ pub fn build_impl( } else { ( tcx.associated_items(did) + .iter() .filter_map(|item| { if associated_trait.is_some() || item.vis == ty::Visibility::Public { Some(item.clean(cx)) @@ -401,9 +402,7 @@ pub fn build_impl( let provided = trait_ .def_id() - .map(|did| { - tcx.provided_trait_methods(did).into_iter().map(|meth| meth.ident.to_string()).collect() - }) + .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.ident.to_string()).collect()) .unwrap_or_default(); debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id()); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f140f11b09098..87edc88611f3a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2108,11 +2108,7 @@ impl Clean> for doctree::Impl<'_> { let provided: FxHashSet = trait_ .def_id() .map(|did| { - cx.tcx - .provided_trait_methods(did) - .into_iter() - .map(|meth| meth.ident.to_string()) - .collect() + cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.to_string()).collect() }) .unwrap_or_default(); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 332d19fbfaeca..9ecf6d531299f 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -206,6 +206,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { return cx .tcx .associated_items(did) + .iter() .find(|item| item.ident.name == item_name) .and_then(|item| match item.kind { ty::AssocKind::Method => Some("method"), diff --git a/src/test/pretty/gat-bounds.pp b/src/test/pretty/gat-bounds.pp new file mode 100644 index 0000000000000..0c95add490110 --- /dev/null +++ b/src/test/pretty/gat-bounds.pp @@ -0,0 +1,25 @@ +// Check that associated types print generic parameters and where clauses. +// See issue #67509. + +// pretty-compare-only +// pp-exact:gat-bounds.pp + +#![feature(generic_associated_types)] + +trait X { + type + Y: Trait + where + Self: Sized; +} + +impl X for () { + type + Y + where + Self: Sized + = + u32; +} + +fn main() { } diff --git a/src/test/pretty/gat-bounds.rs b/src/test/pretty/gat-bounds.rs new file mode 100644 index 0000000000000..1275f432a3c50 --- /dev/null +++ b/src/test/pretty/gat-bounds.rs @@ -0,0 +1,17 @@ +// Check that associated types print generic parameters and where clauses. +// See issue #67509. + +// pretty-compare-only +// pp-exact:gat-bounds.pp + +#![feature(generic_associated_types)] + +trait X { + type Y: Trait where Self: Sized; +} + +impl X for () { + type Y where Self: Sized = u32; +} + +fn main() { }