From fc5c31c48cf19757ebf4b750efa34e7cb5f995e3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 9 Jun 2017 10:55:16 +0300 Subject: [PATCH] rustc: make the comon case of tcx.infer_ctxt(()) nicer. --- src/librustc/infer/mod.rs | 100 ++++++------------ src/librustc/traits/error_reporting.rs | 19 ++-- src/librustc/traits/mod.rs | 4 +- src/librustc/traits/specialize/mod.rs | 4 +- .../traits/specialize/specialization_graph.rs | 2 +- src/librustc/traits/trans/mod.rs | 2 +- src/librustc/ty/util.rs | 8 +- src/librustc_const_eval/eval.rs | 2 +- src/librustc_driver/test.rs | 2 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_mir/build/mod.rs | 4 +- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_mir/transform/type_check.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 4 +- src/librustc_typeck/check/dropck.rs | 2 +- src/librustc_typeck/check/mod.rs | 49 +++++++-- src/librustc_typeck/coherence/builtin.rs | 2 +- .../coherence/inherent_impls_overlap.rs | 2 +- src/librustc_typeck/lib.rs | 2 +- 19 files changed, 102 insertions(+), 112 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index b3e5f13de2c..4bc0005d568 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -31,7 +31,7 @@ use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use ty::relate::RelateResult; use traits::{self, ObligationCause, PredicateObligations, Reveal}; use rustc_data_structures::unify::{self, UnificationTable}; -use std::cell::{Cell, RefCell, Ref, RefMut}; +use std::cell::{Cell, RefCell, Ref}; use std::fmt; use syntax::ast; use errors::DiagnosticBuilder; @@ -72,39 +72,14 @@ pub type Bound = Option; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult = Result; // "fixup result" -/// A version of &ty::TypeckTables which can be `Missing` (not needed), -/// `InProgress` (during typeck) or `Interned` (result of typeck). -/// Only the `InProgress` version supports `borrow_mut`. -#[derive(Copy, Clone)] -pub enum InferTables<'a, 'tcx: 'a> { - InProgress(&'a RefCell>), - Missing -} - -impl<'a, 'tcx> InferTables<'a, 'tcx> { - pub fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> { - match self { - InferTables::InProgress(tables) => tables.borrow(), - InferTables::Missing => { - bug!("InferTables: infcx.tables.borrow() with no tables") - } - } - } - - pub fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> { - match self { - InferTables::InProgress(tables) => tables.borrow_mut(), - InferTables::Missing => { - bug!("InferTables: infcx.tables.borrow_mut() with no tables") - } - } - } -} - pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, - pub tables: InferTables<'a, '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. @@ -360,23 +335,7 @@ impl fmt::Display for FixupError { } } -pub trait InferEnv<'a, 'tcx> { - fn fresh_tables(self) -> Option>; -} - -impl<'a, 'tcx> InferEnv<'a, 'tcx> for () { - fn fresh_tables(self) -> Option> { - None - } -} - -impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::TypeckTables<'tcx> { - fn fresh_tables(self) -> Option> { - Some(self) - } -} - -/// Helper type of a temporary returned by tcx.infer_ctxt(...). +/// Helper type of a temporary returned by tcx.infer_ctxt(). /// Necessary because we can't write the following bound: /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>). pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { @@ -386,16 +345,23 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { - pub fn infer_ctxt>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> { + pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> { InferCtxtBuilder { global_tcx: self, arena: DroplessArena::new(), - fresh_tables: env.fresh_tables().map(RefCell::new), + fresh_tables: None, } } } impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { + /// Used only by `rustc_typeck` during body type-checking/inference, + /// will initialize `in_progress_tables` with fresh `TypeckTables`. + pub fn with_fresh_in_progress_tables(mut self) -> Self { + self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty())); + self + } + pub fn enter(&'tcx mut self, f: F) -> R where F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R { @@ -404,11 +370,10 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { ref arena, ref fresh_tables, } = *self; - let tables = fresh_tables.as_ref() - .map_or(InferTables::Missing, InferTables::InProgress); + let in_progress_tables = fresh_tables.as_ref(); global_tcx.enter_local(arena, |tcx| f(InferCtxt { - tcx: tcx, - tables: tables, + tcx, + in_progress_tables, projection_cache: RefCell::new(traits::ProjectionCache::new()), type_variables: RefCell::new(type_variable::TypeVariableTable::new()), int_unification_table: RefCell::new(UnificationTable::new()), @@ -531,7 +496,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - self.infer_ctxt(()).enter(|infcx| { + self.infer_ctxt().enter(|infcx| { value.trans_normalize(&infcx, param_env) }) } @@ -553,7 +518,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - self.infer_ctxt(()).enter(|infcx| { + self.infer_ctxt().enter(|infcx| { value.trans_normalize(&infcx, env.reveal_all()) }) } @@ -757,10 +722,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { was_in_snapshot: in_snapshot, // Borrow tables "in progress" (i.e. during typeck) // to ban writes from within a snapshot to them. - _in_progress_tables: match self.tables { - InferTables::InProgress(ref tables) => tables.try_borrow().ok(), - _ => None - } + _in_progress_tables: self.in_progress_tables.map(|tables| { + tables.borrow() + }) } } @@ -1366,14 +1330,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span: Span) -> bool { let ty = self.resolve_type_vars_if_possible(&ty); - if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) { - // Even if the type may have no inference variables, during - // type-checking closure types are in local tables only. - let local_closures = match self.tables { - InferTables::InProgress(_) => ty.has_closure_types(), - _ => false - }; - if !local_closures { + // Even if the type may have no inference variables, during + // type-checking closure types are in local tables only. + if !self.in_progress_tables.is_some() || !ty.has_closure_types() { + if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) { return ty.moves_by_default(self.tcx.global_tcx(), param_env, span); } } @@ -1391,7 +1351,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { def_id: DefId) -> Option { - if let InferTables::InProgress(tables) = self.tables { + if let Some(tables) = self.in_progress_tables { if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { return tables.borrow() .closure_kinds @@ -1409,7 +1369,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> { - if let InferTables::InProgress(tables) = self.tables { + if let Some(tables) = self.in_progress_tables { if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { if let Some(&ty) = tables.borrow().closure_tys.get(&id) { return ty; diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 74bfd977148..64438f586d7 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -29,7 +29,7 @@ use hir::{self, intravisit, Local, Pat, Body}; use hir::intravisit::{Visitor, NestedVisitorMap}; use hir::map::NodeExpr; use hir::def_id::DefId; -use infer::{self, InferCtxt, InferTables}; +use infer::{self, InferCtxt}; use infer::type_variable::TypeVariableOrigin; use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; use std::fmt; @@ -72,9 +72,12 @@ struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { - fn node_matches_type(&mut self, node_id: &'gcx NodeId) -> bool { - match self.infcx.tables.borrow().node_types.get(node_id) { - Some(&ty) => { + fn node_matches_type(&mut self, node_id: NodeId) -> bool { + let ty_opt = self.infcx.in_progress_tables.and_then(|tables| { + tables.borrow().node_id_to_type_opt(node_id) + }); + match ty_opt { + Some(ty) => { let ty = self.infcx.resolve_type_vars_if_possible(&ty); ty.walk().any(|inner_ty| { inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) { @@ -88,7 +91,7 @@ impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { } }) } - _ => false, + None => false, } } } @@ -99,7 +102,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { } fn visit_local(&mut self, local: &'gcx Local) { - if self.found_local_pattern.is_none() && self.node_matches_type(&local.id) { + if self.found_local_pattern.is_none() && self.node_matches_type(local.id) { self.found_local_pattern = Some(&*local.pat); } intravisit::walk_local(self, local); @@ -107,7 +110,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { fn visit_body(&mut self, body: &'gcx Body) { for argument in &body.arguments { - if self.found_arg_pattern.is_none() && self.node_matches_type(&argument.id) { + if self.found_arg_pattern.is_none() && self.node_matches_type(argument.id) { self.found_arg_pattern = Some(&*argument.pat); } } @@ -654,7 +657,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Additional context information explaining why the closure only implements // a particular trait. - if let InferTables::InProgress(tables) = self.tables { + if let Some(tables) = self.in_progress_tables { match tables.borrow().closure_kinds.get(&node_id) { Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => { err.span_note(span, &format!( diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index c51974e6e67..3ce7ee847cc 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -484,7 +484,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let predicates = match fully_normalize( &infcx, cause, @@ -598,7 +598,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("normalize_and_test_predicates(predicates={:?})", predicates); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::All); let mut selcx = SelectionContext::new(&infcx); let mut fulfill_cx = FulfillmentContext::new(); diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 689f06a3597..18734e2dbc3 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -125,7 +125,7 @@ pub fn find_associated_item<'a, 'tcx>( let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id); match ancestors.defs(tcx, item.name, item.kind).next() { Some(node_item) => { - let substs = tcx.infer_ctxt(()).enter(|infcx| { + let substs = tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::All); let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id, @@ -188,7 +188,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap(); // Create a infcx, taking the predicates of impl1 as assumptions: - let result = tcx.infer_ctxt(()).enter(|infcx| { + let result = tcx.infer_ctxt().enter(|infcx| { // Normalize the trait reference. The WF rules ought to ensure // that this always succeeds. let impl1_trait_ref = diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 702c5035a18..f80caeec460 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -109,7 +109,7 @@ impl<'a, 'gcx, 'tcx> Children { let possible_sibling = *slot; let tcx = tcx.global_tcx(); - let (le, ge) = tcx.infer_ctxt(()).enter(|infcx| { + let (le, ge) = tcx.infer_ctxt().enter(|infcx| { let overlap = traits::overlapping_impls(&infcx, possible_sibling, impl_def_id); diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs index 7ad2ef90f0d..734ba2a2d39 100644 --- a/src/librustc/traits/trans/mod.rs +++ b/src/librustc/traits/trans/mod.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - self.infer_ctxt(()).enter(|infcx| { + self.infer_ctxt().enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); let param_env = ty::ParamEnv::empty(Reveal::All); diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index ec4ca54d6f5..a7029ac5fa9 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -175,7 +175,7 @@ impl<'tcx> ty::ParamEnv<'tcx> { self_type: Ty<'tcx>, span: Span) -> Result<(), CopyImplementationError<'tcx>> { // FIXME: (@jroesch) float this code up - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let (adt, substs) = match self_type.sty { ty::TyAdt(adt, substs) => (adt, substs), _ => return Err(CopyImplementationError::NotAnAdt), @@ -977,7 +977,7 @@ fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem); - tcx.infer_ctxt(()) + tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound(&infcx, param_env, ty, @@ -991,7 +991,7 @@ fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem); - tcx.infer_ctxt(()) + tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound(&infcx, param_env, ty, @@ -1005,7 +1005,7 @@ fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem); - tcx.infer_ctxt(()) + tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound(&infcx, param_env, ty, diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 3d07ffc2bc7..ec7510546a0 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -483,7 +483,7 @@ fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("resolve_trait_associated_const: trait_ref={:?}", trait_ref); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let mut selcx = traits::SelectionContext::new(&infcx); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 2b74d0a812b..62e20a90f8a 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -154,7 +154,7 @@ fn test_env(source_string: &str, index, "test_crate", |tcx| { - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let mut region_maps = RegionMaps::new(); body(Env { infcx: &infcx, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index bccdac91423..9800012917c 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -956,7 +956,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { cx.param_env, trait_ref.to_poly_trait_predicate()); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); match selcx.select(&obligation) { // The method comes from a `T: Trait` bound. diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 8d549154e11..56c0e18d6f9 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -83,7 +83,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t }; let src = MirSource::from_node(tcx, id); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let cx = Cx::new(&infcx, src); let mut mir = if cx.tables().tainted_by_errors { build::construct_error(cx, body_id) @@ -171,7 +171,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let span = tcx.hir.span(ctor_id); if let hir::VariantData::Tuple(ref fields, ctor_id) = *v { - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let (mut mir, src) = shim::build_adt_ctor(&infcx, ctor_id, fields, span); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 793cffdec89..d60e761bc0b 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -998,7 +998,7 @@ impl MirPass for QualifyAndPromoteConstants { // Statics must be Sync. if mode == Mode::Static { let ty = mir.return_ty; - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); let mut fulfillment_cx = traits::FulfillmentContext::new(); diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index da8e3b5a42b..e23f0705b6a 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -759,7 +759,7 @@ impl MirPass for TypeckMir { return; } let param_env = tcx.param_env(def_id); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let mut checker = TypeChecker::new(&infcx, item_id, param_env); { let mut verifier = TypeVerifier::new(&mut checker, mir); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 8b76431fd2e..29742469f84 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -219,7 +219,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env, normalize_cause.clone()); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let inh = Inherited::new(infcx, impl_m.def_id); let infcx = &inh.infcx; @@ -726,7 +726,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_trait_ref: ty::TraitRef<'tcx>) { debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let inh = Inherited::new(infcx, impl_c.def_id); let infcx = &inh.infcx; diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index bff9289de50..93057f91997 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -79,7 +79,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( // check that the impl type can be made to match the trait type. - tcx.infer_ctxt(()).enter(|ref infcx| { + tcx.infer_ctxt().enter(|ref infcx| { let impl_param_env = tcx.param_env(self_type_did); let tcx = infcx.tcx; let mut fulfillment_cx = traits::FulfillmentContext::new(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f2fdc59762b..844065cb334 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -108,7 +108,7 @@ use lint; use util::common::{ErrorReported, indenter}; use util::nodemap::{DefIdMap, FxHashMap, NodeMap}; -use std::cell::{Cell, RefCell}; +use std::cell::{Cell, RefCell, Ref, RefMut}; use std::collections::hash_map::Entry; use std::cmp; use std::mem::replace; @@ -147,6 +147,33 @@ mod compare_method; mod intrinsic; mod op; +/// A wrapper for InferCtxt's `in_progress_tables` field. +#[derive(Copy, Clone)] +struct MaybeInProgressTables<'a, 'tcx: 'a> { + maybe_tables: Option<&'a RefCell>>, +} + +impl<'a, 'tcx> MaybeInProgressTables<'a, 'tcx> { + fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> { + match self.maybe_tables { + Some(tables) => tables.borrow(), + None => { + bug!("MaybeInProgressTables: inh/fcx.tables.borrow() with no tables") + } + } + } + + fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> { + match self.maybe_tables { + Some(tables) => tables.borrow_mut(), + None => { + bug!("MaybeInProgressTables: inh/fcx.tables.borrow_mut() with no tables") + } + } + } +} + + /// closures defined within the function. For example: /// /// fn foo() { @@ -159,6 +186,8 @@ mod op; pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: InferCtxt<'a, 'gcx, 'tcx>, + tables: MaybeInProgressTables<'a, 'tcx>, + locals: RefCell>>, fulfillment_cx: RefCell>, @@ -535,9 +564,8 @@ pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId) -> InheritedBuilder<'a, 'gcx, 'tcx> { - let tables = ty::TypeckTables::empty(); InheritedBuilder { - infcx: tcx.infer_ctxt(tables), + infcx: tcx.infer_ctxt().with_fresh_in_progress_tables(), def_id, } } @@ -562,6 +590,9 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { }); Inherited { + tables: MaybeInProgressTables { + maybe_tables: infcx.in_progress_tables, + }, infcx: infcx, fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), locals: RefCell::new(NodeMap()), @@ -3302,14 +3333,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_expr_has_type(base_expr, struct_ty); match struct_ty.sty { ty::TyAdt(adt, substs) if adt.is_struct() => { - self.tables.borrow_mut().fru_field_types.insert( - expr.id, - adt.struct_variant().fields.iter().map(|f| { - self.normalize_associated_types_in( - expr.span, &f.ty(self.tcx, substs) - ) - }).collect() - ); + let fru_field_types = adt.struct_variant().fields.iter().map(|f| { + self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs)) + }).collect(); + self.tables.borrow_mut().fru_field_types.insert(expr.id, fru_field_types); } _ => { span_err!(self.tcx.sess, base_expr.span, E0436, diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 377b7b069d3..ccbc0299041 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -208,7 +208,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, source, target); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let cause = ObligationCause::misc(span, impl_node_id); let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>, diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index afeb85a7a06..078ae34bc52 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -70,7 +70,7 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { for (i, &impl1_def_id) in impls.iter().enumerate() { for &impl2_def_id in &impls[(i + 1)..] { - self.tcx.infer_ctxt(()).enter(|infcx| { + self.tcx.infer_ctxt().enter(|infcx| { if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() { self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id) } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 06cb9f948c9..26ea3ab3a33 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -155,7 +155,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>) -> bool { - tcx.infer_ctxt(()).enter(|ref infcx| { + tcx.infer_ctxt().enter(|ref infcx| { let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let mut fulfill_cx = FulfillmentContext::new(); match infcx.at(&cause, param_env).eq(expected, actual) {