From a1c170fc355947f54129a97aedcb8dea3d555f71 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 11 May 2016 04:14:41 +0300 Subject: [PATCH] rustc: Split local type contexts interners from the global one. --- src/librustc/infer/mod.rs | 247 ++++++++--- src/librustc/middle/intrinsicck.rs | 14 +- src/librustc/middle/liveness.rs | 5 +- src/librustc/mir/tcx.rs | 18 +- src/librustc/traits/coherence.rs | 16 +- src/librustc/traits/mod.rs | 15 +- src/librustc/traits/specialize/mod.rs | 11 +- .../traits/specialize/specialization_graph.rs | 5 +- src/librustc/traits/structural_impls.rs | 52 +++ src/librustc/ty/context.rs | 407 ++++++++++-------- src/librustc/ty/flags.rs | 15 +- src/librustc/ty/layout.rs | 50 +-- src/librustc/ty/mod.rs | 37 +- src/librustc/ty/structural_impls.rs | 35 ++ src/librustc/ty/util.rs | 37 +- src/librustc/util/ppaux.rs | 22 +- src/librustc_borrowck/borrowck/check_loans.rs | 22 +- .../borrowck/gather_loans/mod.rs | 36 +- src/librustc_borrowck/borrowck/mod.rs | 6 +- src/librustc_const_eval/check_match.rs | 15 +- src/librustc_const_eval/eval.rs | 3 +- src/librustc_driver/test.rs | 10 +- src/librustc_lint/builtin.rs | 3 +- src/librustc_mir/build/block.rs | 2 +- src/librustc_mir/build/expr/as_constant.rs | 2 +- src/librustc_mir/build/expr/as_lvalue.rs | 2 +- src/librustc_mir/build/expr/as_operand.rs | 2 +- src/librustc_mir/build/expr/as_rvalue.rs | 2 +- src/librustc_mir/build/expr/as_temp.rs | 2 +- src/librustc_mir/build/expr/into.rs | 2 +- src/librustc_mir/build/expr/stmt.rs | 2 +- src/librustc_mir/build/into.rs | 32 +- src/librustc_mir/build/matches/mod.rs | 4 +- src/librustc_mir/build/matches/simplify.rs | 2 +- src/librustc_mir/build/matches/test.rs | 2 +- src/librustc_mir/build/matches/util.rs | 2 +- src/librustc_mir/build/misc.rs | 2 +- src/librustc_mir/build/mod.rs | 34 +- src/librustc_mir/build/scope.rs | 28 +- src/librustc_mir/hair/cx/block.rs | 16 +- src/librustc_mir/hair/cx/expr.rs | 81 ++-- src/librustc_mir/hair/cx/mod.rs | 25 +- src/librustc_mir/hair/cx/pattern.rs | 23 +- src/librustc_mir/hair/mod.rs | 12 +- src/librustc_mir/mir_map.rs | 127 ++++-- src/librustc_mir/transform/qualify_consts.rs | 3 +- src/librustc_mir/transform/type_check.rs | 18 +- src/librustc_passes/consts.rs | 13 +- src/librustc_passes/rvalues.rs | 20 +- src/librustc_trans/_match.rs | 3 +- src/librustc_trans/closure.rs | 8 +- src/librustc_trans/collector.rs | 10 +- src/librustc_trans/common.rs | 14 +- src/librustc_trans/glue.rs | 20 +- src/librustc_trans/meth.rs | 11 +- src/librustc_trans/mir/constant.rs | 3 +- src/librustc_trans/monomorphize.rs | 3 +- src/librustc_trans/type_of.rs | 3 +- src/librustc_typeck/check/compare_method.rs | 39 +- src/librustc_typeck/check/dropck.rs | 5 +- src/librustc_typeck/check/mod.rs | 45 +- src/librustc_typeck/check/wfcheck.rs | 120 ++++-- src/librustc_typeck/coherence/mod.rs | 14 +- src/librustc_typeck/coherence/overlap.rs | 3 +- src/librustc_typeck/lib.rs | 4 +- 65 files changed, 1144 insertions(+), 702 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index e6d9db20ecef..fe9e128d8a6c 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -24,6 +24,7 @@ use middle::free_region::FreeRegionMap; use middle::mem_categorization as mc; use middle::mem_categorization::McResult; use middle::region::CodeExtent; +use mir::tcx::LvalueTy; use ty::subst; use ty::subst::Substs; use ty::subst::Subst; @@ -35,7 +36,7 @@ use ty::fold::TypeFoldable; use ty::relate::{Relate, RelateResult, TypeRelation}; use traits::{self, PredicateObligations, ProjectionMode}; use rustc_data_structures::unify::{self, UnificationTable}; -use std::cell::{Cell, RefCell, Ref}; +use std::cell::{Cell, RefCell, Ref, RefMut}; use std::fmt; use syntax::ast; use syntax::codemap; @@ -72,10 +73,36 @@ pub type Bound = Option; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult = Result; // "fixup result" +/// A version of &ty::Tables which can be global or local. +/// Only the local version supports borrow_mut. +#[derive(Copy, Clone)] +pub enum InferTables<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + Global(&'a RefCell>), + Local(&'a RefCell>) +} + +impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> { + pub fn borrow(self) -> Ref<'a, ty::Tables<'tcx>> { + match self { + InferTables::Global(tables) => tables.borrow(), + InferTables::Local(tables) => tables.borrow() + } + } + + pub fn borrow_mut(self) -> RefMut<'a, ty::Tables<'tcx>> { + match self { + InferTables::Global(_) => { + bug!("InferTables: infcx.tables.borrow_mut() outside of type-checking"); + } + InferTables::Local(tables) => tables.borrow_mut() + } + } +} + pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, - pub tables: &'a RefCell>, + pub tables: InferTables<'a, 'gcx, 'tcx>, // We instantiate UnificationTable with bounds because the // types that might instantiate a general type variable have an @@ -390,48 +417,106 @@ impl fmt::Display for FixupError { } } -impl<'a, 'tcx> InferCtxt<'a, 'tcx, 'tcx> { - pub fn enter(tcx: TyCtxt<'a, 'tcx, 'tcx>, - tables: Option>, - param_env: Option>, - projection_mode: ProjectionMode, - f: F) -> R - where F: for<'b> FnOnce(InferCtxt<'b, 'tcx, 'tcx>) -> R +/// 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> { + global_tcx: TyCtxt<'a, 'gcx, 'gcx>, + arenas: ty::CtxtArenas<'tcx>, + tables: Option>>, + param_env: Option>, + projection_mode: ProjectionMode, + normalize: bool +} + +impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { + pub fn infer_ctxt(self, + tables: Option>, + param_env: Option>, + projection_mode: ProjectionMode) + -> InferCtxtBuilder<'a, 'gcx, 'tcx> { + InferCtxtBuilder { + global_tcx: self, + arenas: ty::CtxtArenas::new(), + tables: tables.map(RefCell::new), + param_env: param_env, + projection_mode: projection_mode, + normalize: false + } + } + + pub fn normalizing_infer_ctxt(self, projection_mode: ProjectionMode) + -> InferCtxtBuilder<'a, 'gcx, 'tcx> { + InferCtxtBuilder { + global_tcx: self, + arenas: ty::CtxtArenas::new(), + tables: None, + param_env: None, + projection_mode: projection_mode, + normalize: false + } + } + + /// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck + /// for MemCategorizationContext/ExprUseVisitor. + /// If any inference functionality is used, ICEs will occur. + pub fn borrowck_fake_infer_ctxt(self, param_env: ty::ParameterEnvironment<'gcx>) + -> InferCtxt<'a, 'gcx, 'gcx> { + InferCtxt { + tcx: self, + tables: InferTables::Global(&self.tables), + type_variables: RefCell::new(type_variable::TypeVariableTable::new()), + int_unification_table: RefCell::new(UnificationTable::new()), + float_unification_table: RefCell::new(UnificationTable::new()), + region_vars: RegionVarBindings::new(self), + parameter_environment: param_env, + selection_cache: traits::SelectionCache::new(), + evaluation_cache: traits::EvaluationCache::new(), + reported_trait_errors: RefCell::new(FnvHashSet()), + normalize: false, + projection_mode: ProjectionMode::AnyFinal, + tainted_by_errors_flag: Cell::new(false), + err_count_on_creation: self.sess.err_count() + } + } +} + +impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { + pub fn enter(&'tcx mut self, f: F) -> R + where F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R { - let new_tables; - let tables = if let Some(tables) = tables { - new_tables = RefCell::new(tables); - &new_tables + let InferCtxtBuilder { + global_tcx, + ref arenas, + ref tables, + ref mut param_env, + projection_mode, + normalize + } = *self; + let tables = if let Some(ref tables) = *tables { + InferTables::Local(tables) } else { - &tcx.tables + InferTables::Global(&global_tcx.tables) }; - f(InferCtxt { + let param_env = param_env.take().unwrap_or_else(|| { + global_tcx.empty_parameter_environment() + }); + global_tcx.enter_local(arenas, |tcx| f(InferCtxt { tcx: tcx, tables: tables, type_variables: RefCell::new(type_variable::TypeVariableTable::new()), int_unification_table: RefCell::new(UnificationTable::new()), float_unification_table: RefCell::new(UnificationTable::new()), region_vars: RegionVarBindings::new(tcx), - parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()), + parameter_environment: param_env, selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), reported_trait_errors: RefCell::new(FnvHashSet()), - normalize: false, + normalize: normalize, projection_mode: projection_mode, - tainted_by_errors_flag: Cell::new(false), + tainted_by_errors_flag: Cell::new(false), err_count_on_creation: tcx.sess.err_count() - }) - } - - pub fn enter_normalizing(tcx: TyCtxt<'a, 'tcx, 'tcx>, - projection_mode: ProjectionMode, - f: F) -> R - where F: for<'b> FnOnce(InferCtxt<'b, 'tcx, 'tcx>) -> R - { - InferCtxt::enter(tcx, None, None, projection_mode, |mut infcx| { - infcx.normalize = true; - f(infcx) - }) + })) } } @@ -459,10 +544,54 @@ pub struct CombinedSnapshot { region_vars_snapshot: RegionSnapshot, } +/// Helper trait for shortening the lifetimes inside a +/// value for post-type-checking normalization. +pub trait TransNormalize<'gcx>: TypeFoldable<'gcx> { + fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self; +} + +macro_rules! items { ($($item:item)+) => ($($item)+) } +macro_rules! impl_trans_normalize { + ($lt_gcx:tt, $($ty:ty),+) => { + items!($(impl<$lt_gcx> TransNormalize<$lt_gcx> for $ty { + fn trans_normalize<'a, 'tcx>(&self, + infcx: &InferCtxt<'a, $lt_gcx, 'tcx>) + -> Self { + infcx.normalize_projections_in(self) + } + })+); + } +} + +impl_trans_normalize!('gcx, + Ty<'gcx>, + &'gcx Substs<'gcx>, + ty::FnSig<'gcx>, + ty::FnOutput<'gcx>, + &'gcx ty::BareFnTy<'gcx>, + ty::ClosureSubsts<'gcx>, + ty::PolyTraitRef<'gcx> +); + +impl<'gcx> TransNormalize<'gcx> for LvalueTy<'gcx> { + fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self { + match *self { + LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.trans_normalize(infcx) }, + LvalueTy::Downcast { adt_def, substs, variant_index } => { + LvalueTy::Downcast { + adt_def: adt_def, + substs: substs.trans_normalize(infcx), + variant_index: variant_index + } + } + } + } +} + // NOTE: Callable from trans only! impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { pub fn normalize_associated_type(self, value: &T) -> T - where T : TypeFoldable<'tcx> + where T: TransNormalize<'tcx> { debug!("normalize_associated_type(t={:?})", value); @@ -472,15 +601,15 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - InferCtxt::enter(self, None, None, ProjectionMode::Any, |infcx| { - infcx.normalize_projections_in(&value) + self.infer_ctxt(None, None, ProjectionMode::Any).enter(|infcx| { + value.trans_normalize(&infcx) }) } } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - fn normalize_projections_in(&self, value: &T) -> T - where T : TypeFoldable<'tcx> + fn normalize_projections_in(&self, value: &T) -> T::Lifted + where T: TypeFoldable<'tcx> + ty::Lift<'gcx> { let mut selcx = traits::SelectionContext::new(self); let cause = traits::ObligationCause::dummy(); @@ -503,16 +632,21 @@ pub fn drain_fulfillment_cx_or_panic(&self, span: Span, fulfill_cx: &mut traits::FulfillmentContext<'tcx>, result: &T) - -> T - where T : TypeFoldable<'tcx> + -> T::Lifted + where T: TypeFoldable<'tcx> + ty::Lift<'gcx> { - match self.drain_fulfillment_cx(fulfill_cx, result) { + let when = "resolving bounds after type-checking"; + let v = match self.drain_fulfillment_cx(fulfill_cx, result) { Ok(v) => v, Err(errors) => { - span_bug!( - span, - "Encountered errors `{:?}` fulfilling during trans", - errors); + span_bug!(span, "Encountered errors `{:?}` {}", errors, when); + } + }; + + match self.tcx.lift_to_global(&v) { + Some(v) => v, + None => { + span_bug!(span, "Uninferred types/regions in `{:?}` {}", v, when); } } } @@ -1449,18 +1583,16 @@ pub fn drain_fulfillment_cx(&self, self.resolve_type_vars_or_error(&ty) } - pub fn tables_are_tcx_tables(&self) -> bool { - let tables: &RefCell = &self.tables; - let tcx_tables: &RefCell = &self.tcx.tables; - tables as *const _ as usize == tcx_tables as *const _ as usize - } - pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool { let ty = self.resolve_type_vars_if_possible(&ty); if let Some(ty) = self.tcx.lift_to_global(&ty) { - // HACK(eddyb) Temporarily handle infer type in the global tcx. - if !ty.needs_infer() && - !(ty.has_closure_types() && !self.tables_are_tcx_tables()) { + // 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::Local(_) => ty.has_closure_types(), + InferTables::Global(_) => false + }; + if !local_closures { return ty.moves_by_default(self.tcx.global_tcx(), self.param_env(), span); } } @@ -1527,7 +1659,7 @@ pub fn drain_fulfillment_cx(&self, // during trans, we see closure ids from other traits. // That may require loading the closure data out of the // cstore. - Some(ty::Tables::closure_kind(&self.tables, self.tcx, def_id)) + Some(self.tcx.closure_kind(def_id)) } } @@ -1536,12 +1668,13 @@ pub fn drain_fulfillment_cx(&self, substs: ty::ClosureSubsts<'tcx>) -> ty::ClosureTy<'tcx> { - let closure_ty = - ty::Tables::closure_type(self.tables, - self.tcx, - def_id, - substs); + if let InferTables::Local(tables) = self.tables { + if let Some(ty) = tables.borrow().closure_tys.get(&def_id) { + return ty.subst(self.tcx, substs.func_substs); + } + } + let closure_ty = self.tcx.closure_type(def_id, substs); if self.normalize { let closure_ty = self.tcx.erase_regions(&closure_ty); diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index e45d3331a028..07e69d85ff41 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -36,7 +36,7 @@ struct ItemVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> ItemVisitor<'a, 'tcx> { fn visit_const(&mut self, item_id: ast::NodeId, expr: &hir::Expr) { let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id); - InferCtxt::enter(self.tcx, None, Some(param_env), ProjectionMode::Any, |infcx| { + self.tcx.infer_ctxt(None, Some(param_env), ProjectionMode::Any).enter(|infcx| { let mut visitor = ExprVisitor { infcx: &infcx }; @@ -49,7 +49,7 @@ struct ExprVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx> } -impl<'a, 'tcx> ExprVisitor<'a, 'tcx, 'tcx> { +impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> { fn def_id_is_transmute(&self, def_id: DefId) -> bool { let intrinsic = match self.infcx.tcx.lookup_item_type(def_id).ty.sty { ty::TyFnDef(_, _, ref bfty) => bfty.abi == RustIntrinsic, @@ -58,7 +58,7 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx, 'tcx> { intrinsic && self.infcx.tcx.item_name(def_id).as_str() == "transmute" } - fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>, id: ast::NodeId) { + fn check_transmute(&self, span: Span, from: Ty<'gcx>, to: Ty<'gcx>, id: ast::NodeId) { let sk_from = SizeSkeleton::compute(from, self.infcx); let sk_to = SizeSkeleton::compute(to, self.infcx); @@ -84,7 +84,7 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx, 'tcx> { } // Try to display a sensible error with as much information as possible. - let skeleton_string = |ty: Ty<'tcx>, sk| { + let skeleton_string = |ty: Ty<'gcx>, sk| { match sk { Ok(SizeSkeleton::Known(size)) => { format!("{} bits", size.bits()) @@ -114,7 +114,7 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> { // const, static and N in [T; N]. fn visit_expr(&mut self, expr: &hir::Expr) { - InferCtxt::enter(self.tcx, None, None, ProjectionMode::Any, |infcx| { + self.tcx.infer_ctxt(None, None, ProjectionMode::Any).enter(|infcx| { let mut visitor = ExprVisitor { infcx: &infcx }; @@ -144,7 +144,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> { span_bug!(s, "intrinsicck: closure outside of function") } let param_env = ty::ParameterEnvironment::for_item(self.tcx, id); - InferCtxt::enter(self.tcx, None, Some(param_env), ProjectionMode::Any, |infcx| { + self.tcx.infer_ctxt(None, Some(param_env), ProjectionMode::Any).enter(|infcx| { let mut visitor = ExprVisitor { infcx: &infcx }; @@ -153,7 +153,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> { } } -impl<'a, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'tcx, 'tcx> { +impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'gcx, 'tcx> { fn visit_expr(&mut self, expr: &hir::Expr) { if let hir::ExprPath(..) = expr.node { match self.infcx.tcx.resolve_expr(expr) { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index de38c51aabef..473fd7d9be65 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -114,7 +114,6 @@ use hir::def::*; use hir::pat_util; use ty::{self, TyCtxt, ParameterEnvironment}; use traits::{self, ProjectionMode}; -use infer::InferCtxt; use ty::subst::Subst; use lint; use util::nodemap::NodeMap; @@ -1488,8 +1487,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let param_env = ParameterEnvironment::for_item(self.ir.tcx, id); let t_ret_subst = t_ret.subst(self.ir.tcx, ¶m_env.free_substs); - let is_nil = InferCtxt::enter(self.ir.tcx, None, Some(param_env), - ProjectionMode::Any, |infcx| { + let is_nil = self.ir.tcx.infer_ctxt(None, Some(param_env), + ProjectionMode::Any).enter(|infcx| { let cause = traits::ObligationCause::dummy(); traits::fully_normalize(&infcx, cause, &t_ret_subst).unwrap().is_nil() }); diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 7041945a8730..a1c0d92f60cd 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -30,12 +30,12 @@ pub enum LvalueTy<'tcx> { variant_index: usize }, } -impl<'a, 'tcx> LvalueTy<'tcx> { +impl<'a, 'gcx, 'tcx> LvalueTy<'tcx> { pub fn from_ty(ty: Ty<'tcx>) -> LvalueTy<'tcx> { LvalueTy::Ty { ty: ty } } - pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> { + pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { match *self { LvalueTy::Ty { ty } => ty, @@ -44,7 +44,7 @@ impl<'a, 'tcx> LvalueTy<'tcx> { } } - pub fn projection_ty(self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, elem: &LvalueElem<'tcx>) -> LvalueTy<'tcx> { @@ -99,8 +99,8 @@ impl<'tcx> TypeFoldable<'tcx> for LvalueTy<'tcx> { } } -impl<'a, 'tcx> Mir<'tcx> { - pub fn operand_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, +impl<'a, 'gcx, 'tcx> Mir<'tcx> { + pub fn operand_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, operand: &Operand<'tcx>) -> Ty<'tcx> { @@ -110,7 +110,7 @@ impl<'a, 'tcx> Mir<'tcx> { } } - pub fn binop_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + pub fn binop_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, op: BinOp, lhs_ty: Ty<'tcx>, rhs_ty: Ty<'tcx>) @@ -134,7 +134,7 @@ impl<'a, 'tcx> Mir<'tcx> { } } - pub fn lvalue_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + pub fn lvalue_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, lvalue: &Lvalue<'tcx>) -> LvalueTy<'tcx> { @@ -154,7 +154,7 @@ impl<'a, 'tcx> Mir<'tcx> { } } - pub fn rvalue_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + pub fn rvalue_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, rvalue: &Rvalue<'tcx>) -> Option> { @@ -205,7 +205,7 @@ impl<'a, 'tcx> Mir<'tcx> { )) } AggregateKind::Adt(def, _, substs) => { - Some(def.type_scheme(tcx).ty.subst(tcx, substs)) + Some(tcx.lookup_item_type(def.did).ty.subst(tcx, substs)) } AggregateKind::Closure(did, substs) => { Some(tcx.mk_closure_from_closure_substs(did, substs)) diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 74e6a97daf84..414b9fa70c30 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -24,10 +24,10 @@ struct InferIsLocal(bool); /// If there are types that satisfy both impls, returns a suitably-freshened /// `ImplHeader` with those types substituted -pub fn overlapping_impls<'cx, 'tcx>(infcx: &InferCtxt<'cx, 'tcx, 'tcx>, - impl1_def_id: DefId, - impl2_def_id: DefId) - -> Option> +pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>, + impl1_def_id: DefId, + impl2_def_id: DefId) + -> Option> { debug!("impl_can_satisfy(\ impl1_def_id={:?}, \ @@ -41,10 +41,10 @@ pub fn overlapping_impls<'cx, 'tcx>(infcx: &InferCtxt<'cx, 'tcx, 'tcx>, /// Can both impl `a` and impl `b` be satisfied by a common type (including /// `where` clauses)? If so, returns an `ImplHeader` that unifies the two impls. -fn overlap<'cx, 'tcx>(selcx: &mut SelectionContext<'cx, 'tcx, 'tcx>, - a_def_id: DefId, - b_def_id: DefId) - -> Option> +fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, + a_def_id: DefId, + b_def_id: DefId) + -> Option> { debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index f9b5c0b139c2..f606d73a5493 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -422,7 +422,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let elaborated_env = unnormalized_env.with_caller_bounds(predicates); - InferCtxt::enter(tcx, None, Some(elaborated_env), ProjectionMode::AnyFinal, |infcx| { + tcx.infer_ctxt(None, Some(elaborated_env), ProjectionMode::AnyFinal).enter(|infcx| { let predicates = match fully_normalize(&infcx, cause, &infcx.parameter_environment.caller_bounds) { Ok(predicates) => predicates, @@ -454,6 +454,11 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }; + let predicates = match tcx.lift_to_global(&predicates) { + Some(predicates) => predicates, + None => return infcx.parameter_environment + }; + debug!("normalize_param_env_or_error: resolved predicates={:?}", predicates); @@ -461,10 +466,10 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) } -pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx, 'tcx>, - cause: ObligationCause<'tcx>, - value: &T) - -> Result>> +pub fn fully_normalize<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, + cause: ObligationCause<'tcx>, + value: &T) + -> Result>> where T : TypeFoldable<'tcx> { debug!("fully_normalize(value={:?})", value); diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 9212c54eb7df..d43d2de1f1fb 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -146,14 +146,21 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .unwrap() .subst(tcx, &penv.free_substs); - InferCtxt::enter_normalizing(tcx, ProjectionMode::Topmost, |mut infcx| { + tcx.normalizing_infer_ctxt(ProjectionMode::Topmost).enter(|mut infcx| { // Normalize the trait reference, adding any obligations // that arise into the impl1 assumptions. let Normalized { value: impl1_trait_ref, obligations: normalization_obligations } = { let selcx = &mut SelectionContext::new(&infcx); traits::normalize(selcx, ObligationCause::dummy(), &impl1_trait_ref) }; - penv.caller_bounds.extend(normalization_obligations.into_iter().map(|o| o.predicate)); + penv.caller_bounds.extend(normalization_obligations.into_iter().map(|o| { + match tcx.lift_to_global(&o.predicate) { + Some(predicate) => predicate, + None => { + bug!("specializes: obligation `{:?}` has inference types/regions", o); + } + } + })); // Install the parameter environment, taking the predicates of impl1 as assumptions: infcx.parameter_environment = penv; diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 8c359c0c7a2c..ae7deb48f867 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -14,7 +14,6 @@ use std::rc::Rc; use super::{OverlapError, specializes}; use hir::def_id::DefId; -use infer::InferCtxt; use traits::{self, ProjectionMode}; use ty::{self, TyCtxt, ImplOrTraitItem, TraitDef, TypeFoldable}; use ty::fast_reject::{self, SimplifiedType}; @@ -112,8 +111,8 @@ impl<'a, 'gcx, 'tcx> Children { let possible_sibling = *slot; let tcx = tcx.global_tcx(); - let (le, ge) = InferCtxt::enter(tcx, None, None, - ProjectionMode::Topmost, |infcx| { + let (le, ge) = tcx.infer_ctxt(None, None, + ProjectionMode::Topmost).enter(|infcx| { let overlap = traits::overlapping_impls(&infcx, possible_sibling, impl_def_id); diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 8d3f7fab38f8..1495ae72ab34 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -153,6 +153,58 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> { } } +// For trans only. +impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> { + type Lifted = traits::Vtable<'tcx, ()>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + match self.clone() { + traits::VtableImpl(traits::VtableImplData { + impl_def_id, + substs, + nested + }) => { + tcx.lift(&substs).map(|substs| { + traits::VtableImpl(traits::VtableImplData { + impl_def_id: impl_def_id, + substs: substs, + nested: nested + }) + }) + } + traits::VtableDefaultImpl(t) => Some(traits::VtableDefaultImpl(t)), + traits::VtableClosure(traits::VtableClosureData { + closure_def_id, + substs, + nested + }) => { + tcx.lift(&substs).map(|substs| { + traits::VtableClosure(traits::VtableClosureData { + closure_def_id: closure_def_id, + substs: substs, + nested: nested + }) + }) + } + traits::VtableFnPointer(ty) => { + tcx.lift(&ty).map(traits::VtableFnPointer) + } + traits::VtableParam(n) => Some(traits::VtableParam(n)), + traits::VtableBuiltin(d) => Some(traits::VtableBuiltin(d)), + traits::VtableObject(traits::VtableObjectData { + upcast_trait_ref, + vtable_base + }) => { + tcx.lift(&upcast_trait_ref).map(|trait_ref| { + traits::VtableObject(traits::VtableObjectData { + upcast_trait_ref: trait_ref, + vtable_base: vtable_base + }) + }) + } + } + } +} + /////////////////////////////////////////////////////////////////////////// // TypeFoldable implementations. diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index f5610de062fb..39fe744c67d0 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -22,7 +22,7 @@ use middle::free_region::FreeRegionMap; use middle::region::RegionMaps; use middle::resolve_lifetime; use middle::stability; -use ty::subst::{self, Subst, Substs}; +use ty::subst::{self, Substs}; use traits; use ty::{self, TraitRef, Ty, TypeAndMut}; use ty::{TyS, TypeVariants}; @@ -41,6 +41,7 @@ use arena::TypedArena; use std::borrow::Borrow; use std::cell::{Cell, RefCell, Ref}; use std::hash::{Hash, Hasher}; +use std::mem; use std::ops::Deref; use std::rc::Rc; use syntax::ast::{self, Name, NodeId}; @@ -82,22 +83,22 @@ impl<'tcx> CtxtArenas<'tcx> { } } -struct CtxtInterners<'tcx> { +pub struct CtxtInterners<'tcx> { /// The arenas that types etc are allocated from. arenas: &'tcx CtxtArenas<'tcx>, /// Specifically use a speedy hash algorithm for these hash sets, /// they're accessed quite often. - type_: RefCell>>, - type_list: RefCell>>, - substs: RefCell>>, - bare_fn: RefCell>>, - region: RefCell>>, + type_: RefCell>>>, + type_list: RefCell]>>>, + substs: RefCell>>>, + bare_fn: RefCell>>>, + region: RefCell>>, stability: RefCell>, layout: RefCell>, } -impl<'tcx> CtxtInterners<'tcx> { +impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { fn new(arenas: &'tcx CtxtArenas<'tcx>) -> CtxtInterners<'tcx> { CtxtInterners { arenas: arenas, @@ -111,24 +112,58 @@ impl<'tcx> CtxtInterners<'tcx> { } } - fn intern_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> { + /// Intern a type. global_interners is Some only if this is + /// a local interner and global_interners is its counterpart. + fn intern_ty(&self, st: TypeVariants<'tcx>, + global_interners: Option<&CtxtInterners<'gcx>>) + -> Ty<'tcx> { let ty = { let mut interner = self.type_.borrow_mut(); - match interner.get(&st) { - Some(&InternedTy { ty }) => return ty, - None => () + let global_interner = global_interners.map(|interners| { + interners.type_.borrow_mut() + }); + if let Some(&Interned(ty)) = interner.get(&st) { + return ty; + } + if let Some(ref interner) = global_interner { + if let Some(&Interned(ty)) = interner.get(&st) { + return ty; + } } let flags = super::flags::FlagComputation::for_sty(&st); - - // Don't be &mut TyS. - let ty: Ty = self.arenas.type_.alloc(TyS { + let ty_struct = TyS { sty: st, flags: Cell::new(flags.flags), region_depth: flags.depth, - }); + }; - interner.insert(InternedTy { ty: ty }); + // HACK(eddyb) Depend on flags being accurate to + // determine that all contents are in the global tcx. + // See comments on Lift for why we can't use that. + if !flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) { + if let Some(interner) = global_interners { + let ty_struct: TyS<'gcx> = unsafe { + mem::transmute(ty_struct) + }; + let ty: Ty<'gcx> = interner.arenas.type_.alloc(ty_struct); + global_interner.unwrap().insert(Interned(ty)); + return ty; + } + } else { + // Make sure we don't end up with inference + // types/regions in the global tcx. + if global_interners.is_none() { + drop(interner); + bug!("Attempted to intern `{:?}` which contains \ + inference types/regions in the global type context", + &ty_struct); + } + } + + // Don't be &mut TyS. + let ty: Ty<'tcx> = self.arenas.type_.alloc(ty_struct); + interner.insert(Interned(ty)); ty }; @@ -212,45 +247,11 @@ impl<'a, 'gcx, 'tcx> Tables<'tcx> { fru_field_types: NodeMap() } } - - pub fn closure_kind(this: &RefCell, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - def_id: DefId) - -> ty::ClosureKind { - // If this is a local def-id, it should be inserted into the - // tables by typeck; else, it will be retreived from - // the external crate metadata. - if let Some(&kind) = this.borrow().closure_kinds.get(&def_id) { - return kind; - } - - let kind = tcx.sess.cstore.closure_kind(def_id); - this.borrow_mut().closure_kinds.insert(def_id, kind); - kind - } - - pub fn closure_type(this: &RefCell, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - def_id: DefId, - substs: ClosureSubsts<'tcx>) - -> ty::ClosureTy<'tcx> - { - // If this is a local def-id, it should be inserted into the - // tables by typeck; else, it will be retreived from - // the external crate metadata. - if let Some(ty) = this.borrow().closure_tys.get(&def_id) { - return ty.subst(tcx, substs.func_substs); - } - - let ty = tcx.sess.cstore.closure_ty(tcx.global_tcx(), def_id); - this.borrow_mut().closure_tys.insert(def_id, ty.clone()); - ty.subst(tcx, substs.func_substs) - } } impl<'tcx> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { - let mk = |sty| interners.intern_ty(sty); + let mk = |sty| interners.intern_ty(sty, None); CommonTypes { bool: mk(TyBool), char: mk(TyChar), @@ -558,13 +559,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { interned } - pub fn intern_stability(self, stab: attr::Stability) -> &'tcx attr::Stability { - if let Some(st) = self.interners.stability.borrow().get(&stab) { + pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability { + if let Some(st) = self.global_interners.stability.borrow().get(&stab) { return st; } - let interned = self.interners.arenas.stability.alloc(stab); - if let Some(prev) = self.interners.stability + let interned = self.global_interners.arenas.stability.alloc(stab); + if let Some(prev) = self.global_interners.stability .borrow_mut() .replace(interned) { bug!("Tried to overwrite interned Stability: {:?}", prev) @@ -572,13 +573,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { interned } - pub fn intern_layout(self, layout: Layout) -> &'tcx Layout { - if let Some(layout) = self.interners.layout.borrow().get(&layout) { + pub fn intern_layout(self, layout: Layout) -> &'gcx Layout { + if let Some(layout) = self.global_interners.layout.borrow().get(&layout) { return layout; } - let interned = self.interners.arenas.layout.alloc(layout); - if let Some(prev) = self.interners.layout + let interned = self.global_interners.arenas.layout.alloc(layout); + if let Some(prev) = self.global_interners.layout .borrow_mut() .replace(interned) { bug!("Tried to overwrite interned Layout: {:?}", prev) @@ -635,7 +636,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let common_types = CommonTypes::new(&interners); let dep_graph = map.dep_graph.clone(); let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone()); - tls::enter(GlobalCtxt { + tls::enter_global(GlobalCtxt { global_interners: interners, dep_graph: dep_graph.clone(), types: common_types, @@ -690,11 +691,27 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } +impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> { + /// Call the closure with a local `TyCtxt` using the given arenas. + pub fn enter_local(&self, arenas: &'tcx CtxtArenas<'tcx>, f: F) -> R + where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R + { + let interners = CtxtInterners::new(arenas); + tls::enter(self, &interners, f) + } +} + /// A trait implemented for all X<'a> types which can be safely and /// efficiently converted to X<'tcx> as long as they are part of the /// provided TyCtxt<'tcx>. /// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx> /// by looking them up in their respective interners. +/// +/// However, this is still not the best implementation as it does +/// need to compare the components, even for interned values. +/// It would be more efficient if TypedArena provided a way to +/// determine whether the address is in the allocated range. +/// /// None is returned if the value or one of the components is not part /// of the provided context. /// For Ty, None can be returned if either the type interner doesn't @@ -709,7 +726,7 @@ pub trait Lift<'tcx> { impl<'a, 'tcx> Lift<'tcx> for Ty<'a> { type Lifted = Ty<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - if let Some(&InternedTy { ty }) = tcx.interners.type_.borrow().get(&self.sty) { + if let Some(&Interned(ty)) = tcx.interners.type_.borrow().get(&self.sty) { if *self as *const _ == ty as *const _ { return Some(ty); } @@ -726,7 +743,7 @@ impl<'a, 'tcx> Lift<'tcx> for Ty<'a> { impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> { type Lifted = &'tcx Substs<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Substs<'tcx>> { - if let Some(&InternedSubsts { substs }) = tcx.interners.substs.borrow().get(*self) { + if let Some(&Interned(substs)) = tcx.interners.substs.borrow().get(*self) { if *self as *const _ == substs as *const _ { return Some(substs); } @@ -743,7 +760,7 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> { impl<'a, 'tcx> Lift<'tcx> for &'a Region { type Lifted = &'tcx Region; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Region> { - if let Some(&InternedRegion { region }) = tcx.interners.region.borrow().get(*self) { + if let Some(&Interned(region)) = tcx.interners.region.borrow().get(*self) { if *self as *const _ == region as *const _ { return Some(region); } @@ -760,7 +777,7 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Region { impl<'a, 'tcx> Lift<'tcx> for &'a [Ty<'a>] { type Lifted = &'tcx [Ty<'tcx>]; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx [Ty<'tcx>]> { - if let Some(&InternedTyList { list }) = tcx.interners.type_list.borrow().get(*self) { + if let Some(&Interned(list)) = tcx.interners.type_list.borrow().get(*self) { if *self as *const _ == list as *const _ { return Some(list); } @@ -774,21 +791,41 @@ impl<'a, 'tcx> Lift<'tcx> for &'a [Ty<'a>] { } } +impl<'a, 'tcx> Lift<'tcx> for &'a BareFnTy<'a> { + type Lifted = &'tcx BareFnTy<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) + -> Option<&'tcx BareFnTy<'tcx>> { + if let Some(&Interned(fty)) = tcx.interners.bare_fn.borrow().get(*self) { + if *self as *const _ == fty as *const _ { + return Some(fty); + } + } + // Also try in the global tcx if we're not that. + if !tcx.is_global() { + self.lift_to_tcx(tcx.global_tcx()) + } else { + None + } + } +} + pub mod tls { - use super::{GlobalCtxt, TyCtxt}; + use super::{CtxtInterners, GlobalCtxt, TyCtxt}; use std::cell::Cell; use std::fmt; use syntax::codemap; - /// Marker type used for the scoped TLS slot. + /// Marker types used for the scoped TLS slot. /// The type context cannot be used directly because the scoped TLS /// in libstd doesn't allow types generic over lifetimes. enum ThreadLocalGlobalCtxt {} + enum ThreadLocalInterners {} thread_local! { - static TLS_TCX: Cell> = Cell::new(None) + static TLS_TCX: Cell> = Cell::new(None) } fn span_debug(span: codemap::Span, f: &mut fmt::Formatter) -> fmt::Result { @@ -797,42 +834,55 @@ pub mod tls { }) } - pub fn enter<'tcx, F, R>(gcx: GlobalCtxt<'tcx>, f: F) -> R - where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>) -> R + pub fn enter_global<'gcx, F, R>(gcx: GlobalCtxt<'gcx>, f: F) -> R + where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'gcx>) -> R { codemap::SPAN_DEBUG.with(|span_dbg| { let original_span_debug = span_dbg.get(); span_dbg.set(span_debug); - let tls_ptr = &gcx as *const _ as *const ThreadLocalGlobalCtxt; - let result = TLS_TCX.with(|tls| { - let prev = tls.get(); - tls.set(Some(tls_ptr)); - let ret = f(gcx.global_tcx()); - tls.set(prev); - ret - }); + let result = enter(&gcx, &gcx.global_interners, f); span_dbg.set(original_span_debug); result }) } - pub fn with(f: F) -> R - where F: for<'a, 'tcx> FnOnce(TyCtxt<'a, 'tcx, 'tcx>) -> R + pub fn enter<'a, 'gcx: 'tcx, 'tcx, F, R>(gcx: &'a GlobalCtxt<'gcx>, + interners: &'a CtxtInterners<'tcx>, + f: F) -> R + where F: FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R { - TLS_TCX.with(|gcx| { - let gcx = gcx.get().unwrap(); + let gcx_ptr = gcx as *const _ as *const ThreadLocalGlobalCtxt; + let interners_ptr = interners as *const _ as *const ThreadLocalInterners; + TLS_TCX.with(|tls| { + let prev = tls.get(); + tls.set(Some((gcx_ptr, interners_ptr))); + let ret = f(TyCtxt { + gcx: gcx, + interners: interners + }); + tls.set(prev); + ret + }) + } + + pub fn with(f: F) -> R + where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R + { + TLS_TCX.with(|tcx| { + let (gcx, interners) = tcx.get().unwrap(); let gcx = unsafe { &*(gcx as *const GlobalCtxt) }; + let interners = unsafe { &*(interners as *const CtxtInterners) }; f(TyCtxt { gcx: gcx, - interners: &gcx.global_interners + interners: interners }) }) } pub fn with_opt(f: F) -> R - where F: for<'a, 'tcx> FnOnce(Option>) -> R + where F: for<'a, 'gcx, 'tcx> FnOnce(Option>) -> R { - if TLS_TCX.with(|gcx| gcx.get().is_some()) { + if TLS_TCX.with(|tcx| tcx.get().is_some()) { with(|v| f(Some(v))) } else { f(None) @@ -847,7 +897,7 @@ macro_rules! sty_debug_print { #[allow(non_snake_case)] mod inner { use ty::{self, TyCtxt}; - use ty::context::InternedTy; + use ty::context::Interned; #[derive(Copy, Clone)] struct DebugStat { @@ -865,7 +915,7 @@ macro_rules! sty_debug_print { $(let mut $variant = total;)* - for &InternedTy { ty: t } in tcx.interners.type_.borrow().iter() { + for &Interned(t) in tcx.interners.type_.borrow().iter() { let variant = match t.sty { ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) | ty::TyFloat(..) | ty::TyStr => continue, @@ -920,68 +970,127 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { } -/// An entry in the type interner. -struct InternedTy<'tcx> { - ty: Ty<'tcx> -} +/// An entry in an interner. +struct Interned<'tcx, T: 'tcx+?Sized>(&'tcx T); -// NB: An InternedTy compares and hashes as a sty. -impl<'tcx> PartialEq for InternedTy<'tcx> { - fn eq(&self, other: &InternedTy<'tcx>) -> bool { - self.ty.sty == other.ty.sty +// NB: An Interned compares and hashes as a sty. +impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> { + fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool { + self.0.sty == other.0.sty } } -impl<'tcx> Eq for InternedTy<'tcx> {} +impl<'tcx> Eq for Interned<'tcx, TyS<'tcx>> {} -impl<'tcx> Hash for InternedTy<'tcx> { +impl<'tcx> Hash for Interned<'tcx, TyS<'tcx>> { fn hash(&self, s: &mut H) { - self.ty.sty.hash(s) + self.0.sty.hash(s) } } -impl<'tcx: 'lcx, 'lcx> Borrow> for InternedTy<'tcx> { +impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, TyS<'tcx>> { fn borrow<'a>(&'a self) -> &'a TypeVariants<'lcx> { - &self.ty.sty + &self.0.sty } } -/// An entry in the type list interner. -#[derive(PartialEq, Eq, Hash)] -struct InternedTyList<'tcx> { - list: &'tcx [Ty<'tcx>] -} - -impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for InternedTyList<'tcx> { +impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for Interned<'tcx, [Ty<'tcx>]> { fn borrow<'a>(&'a self) -> &'a [Ty<'lcx>] { - self.list + self.0 } } -/// An entry in the substs interner. -#[derive(PartialEq, Eq, Hash)] -struct InternedSubsts<'tcx> { - substs: &'tcx Substs<'tcx> -} - -impl<'tcx: 'lcx, 'lcx> Borrow> for InternedSubsts<'tcx> { +impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, Substs<'tcx>> { fn borrow<'a>(&'a self) -> &'a Substs<'lcx> { - self.substs + self.0 } } -/// An entry in the region interner. -#[derive(PartialEq, Eq, Hash)] -struct InternedRegion<'tcx> { - region: &'tcx Region +impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, BareFnTy<'tcx>> { + fn borrow<'a>(&'a self) -> &'a BareFnTy<'lcx> { + self.0 + } } -impl<'tcx> Borrow for InternedRegion<'tcx> { +impl<'tcx> Borrow for Interned<'tcx, Region> { fn borrow<'a>(&'a self) -> &'a Region { - self.region + self.0 } } +macro_rules! items { ($($item:item)+) => ($($item)+) } +macro_rules! impl_interners { + ($lt_tcx:tt, $($name:ident: $method:ident($alloc:ty, $needs_infer:expr)-> $ty:ty),+) => { + items!($(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } + + impl<$lt_tcx> Eq for Interned<$lt_tcx, $ty> {} + + impl<$lt_tcx> Hash for Interned<$lt_tcx, $ty> { + fn hash(&self, s: &mut H) { + self.0.hash(s) + } + } + + impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> { + pub fn $method(self, v: $alloc) -> &$lt_tcx $ty { + if let Some(i) = self.interners.$name.borrow().get::<$ty>(&v) { + return i.0; + } + if !self.is_global() { + if let Some(i) = self.global_interners.$name.borrow().get::<$ty>(&v) { + return i.0; + } + } + + // HACK(eddyb) Depend on flags being accurate to + // determine that all contents are in the global tcx. + // See comments on Lift for why we can't use that. + if !($needs_infer)(&v) { + if !self.is_global() { + let v = unsafe { + mem::transmute(v) + }; + let i = self.global_interners.arenas.$name.alloc(v); + self.global_interners.$name.borrow_mut().insert(Interned(i)); + return i; + } + } else { + // Make sure we don't end up with inference + // types/regions in the global tcx. + if self.is_global() { + bug!("Attempted to intern `{:?}` which contains \ + inference types/regions in the global type context", + v); + } + } + + let i = self.interners.arenas.$name.alloc(v); + self.interners.$name.borrow_mut().insert(Interned(i)); + i + } + })+); + } +} + +fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { + x.has_type_flags(ty::TypeFlags::KEEP_IN_LOCAL_TCX) +} + +impl_interners!('tcx, + type_list: mk_type_list(Vec>, keep_local) -> [Ty<'tcx>], + substs: mk_substs(Substs<'tcx>, |substs: &Substs| { + keep_local(&substs.types) || keep_local(&substs.regions) + }) -> Substs<'tcx>, + bare_fn: mk_bare_fn(BareFnTy<'tcx>, |fty: &BareFnTy| { + keep_local(&fty.sig) + }) -> BareFnTy<'tcx>, + region: mk_region(Region, keep_local) -> Region +); + fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool { bounds.is_empty() || bounds[1..].iter().enumerate().all( @@ -989,31 +1098,6 @@ fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn mk_type_list(self, list: Vec>) -> &'tcx [Ty<'tcx>] { - if let Some(interned) = self.interners.type_list.borrow().get(&list[..]) { - return interned.list; - } - - let list = self.interners.arenas.type_list.alloc(list); - self.interners.type_list.borrow_mut().insert(InternedTyList { - list: list - }); - list - } - - // Type constructors - pub fn mk_substs(self, substs: Substs<'tcx>) -> &'tcx Substs<'tcx> { - if let Some(interned) = self.interners.substs.borrow().get(&substs) { - return interned.substs; - } - - let substs = self.interners.arenas.substs.alloc(substs); - self.interners.substs.borrow_mut().insert(InternedSubsts { - substs: substs - }); - substs - } - /// Create an unsafe fn ty based on a safe fn ty. pub fn safe_to_unsafe_fn_ty(self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> { assert_eq!(bare_fn.unsafety, hir::Unsafety::Normal); @@ -1024,32 +1108,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { })) } - pub fn mk_bare_fn(self, bare_fn: BareFnTy<'tcx>) -> &'tcx BareFnTy<'tcx> { - if let Some(bare_fn) = self.interners.bare_fn.borrow().get(&bare_fn) { - return *bare_fn; - } - - let bare_fn = self.interners.arenas.bare_fn.alloc(bare_fn); - self.interners.bare_fn.borrow_mut().insert(bare_fn); - bare_fn - } - - pub fn mk_region(self, region: Region) -> &'tcx Region { - if let Some(interned) = self.interners.region.borrow().get(®ion) { - return interned.region; - } - - let region = self.interners.arenas.region.alloc(region); - self.interners.region.borrow_mut().insert(InternedRegion { - region: region - }); - region - } - // Interns a type/name combination, stores the resulting box in cx.interners, // and returns the box as cast to an unsafe ptr (see comments for Ty above). pub fn mk_ty(self, st: TypeVariants<'tcx>) -> Ty<'tcx> { - self.interners.intern_ty(st) + let global_interners = if !self.is_global() { + Some(&self.global_interners) + } else { + None + }; + self.interners.intern_ty(st, global_interners) } pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index f3dcccedc594..a1da3017fcd0 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -90,9 +90,15 @@ impl FlagComputation { self.add_tys(&substs.upvar_tys); } - &ty::TyInfer(_) => { + &ty::TyInfer(infer) => { self.add_flags(TypeFlags::HAS_LOCAL_NAMES); // it might, right? - self.add_flags(TypeFlags::HAS_TY_INFER) + self.add_flags(TypeFlags::HAS_TY_INFER); + match infer { + ty::FreshTy(_) | + ty::FreshIntTy(_) | + ty::FreshFloatTy(_) => {} + _ => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX) + } } &ty::TyEnum(_, substs) | &ty::TyStruct(_, substs) => { @@ -171,7 +177,10 @@ impl FlagComputation { fn add_region(&mut self, r: ty::Region) { match r { ty::ReVar(..) | - ty::ReSkolemized(..) => { self.add_flags(TypeFlags::HAS_RE_INFER); } + ty::ReSkolemized(..) => { + self.add_flags(TypeFlags::HAS_RE_INFER); + self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX); + } ty::ReLateBound(debruijn, _) => { self.add_depth(debruijn.depth); } ty::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); } ty::ReStatic => {} diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 35656fb0c2dd..82a3b0b8db28 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -466,7 +466,7 @@ pub struct Struct { pub offset_after_field: Vec } -impl<'a, 'tcx> Struct { +impl<'a, 'gcx, 'tcx> Struct { pub fn new(dl: &TargetDataLayout, packed: bool) -> Struct { Struct { align: if packed { dl.i8_align } else { dl.aggregate_align }, @@ -479,9 +479,9 @@ impl<'a, 'tcx> Struct { /// Extend the Struct with more fields. pub fn extend(&mut self, dl: &TargetDataLayout, fields: I, - scapegoat: Ty<'tcx>) - -> Result<(), LayoutError<'tcx>> - where I: Iterator>> { + scapegoat: Ty<'gcx>) + -> Result<(), LayoutError<'gcx>> + where I: Iterator>> { self.offset_after_field.reserve(fields.size_hint().0); for field in fields { @@ -528,8 +528,8 @@ impl<'a, 'tcx> Struct { /// Determine whether a structure would be zero-sized, given its fields. pub fn would_be_zero_sized(dl: &TargetDataLayout, fields: I) - -> Result> - where I: Iterator>> { + -> Result> + where I: Iterator>> { for field in fields { let field = field?; if field.is_unsized() || field.size(dl).bytes() > 0 { @@ -542,10 +542,10 @@ impl<'a, 'tcx> Struct { /// Find the path leading to a non-zero leaf field, starting from /// the given type and recursing through aggregates. // FIXME(eddyb) track value ranges and traverse already optimized enums. - pub fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'tcx, 'tcx>, - ty: Ty<'tcx>) - -> Result, LayoutError<'tcx>> { - let tcx = infcx.tcx; + pub fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>, + ty: Ty<'gcx>) + -> Result, LayoutError<'gcx>> { + let tcx = infcx.tcx.global_tcx(); match (ty.layout(infcx)?, &ty.sty) { (&Scalar { non_zero: true, .. }, _) => Ok(Some(vec![])), (&FatPointer { non_zero: true, .. }, _) => { @@ -600,10 +600,10 @@ impl<'a, 'tcx> Struct { /// Find the path leading to a non-zero leaf field, starting from /// the given set of fields and recursing through aggregates. - pub fn non_zero_field_path(infcx: &InferCtxt<'a, 'tcx, 'tcx>, + pub fn non_zero_field_path(infcx: &InferCtxt<'a, 'gcx, 'tcx>, fields: I) - -> Result, LayoutError<'tcx>> - where I: Iterator> { + -> Result, LayoutError<'gcx>> + where I: Iterator> { for (i, ty) in fields.enumerate() { if let Some(mut path) = Struct::non_zero_field_in_type(infcx, ty)? { path.push(i as u32); @@ -736,9 +736,9 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { } /// Helper function for normalizing associated types in an inference context. -fn normalize_associated_type<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>, - ty: Ty<'tcx>) - -> Ty<'tcx> { +fn normalize_associated_type<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, + ty: Ty<'gcx>) + -> Ty<'gcx> { if !ty.has_projection_types() { return ty; } @@ -757,11 +757,11 @@ fn normalize_associated_type<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>, infcx.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result) } -impl<'a, 'tcx> Layout { - pub fn compute_uncached(ty: Ty<'tcx>, - infcx: &InferCtxt<'a, 'tcx, 'tcx>) - -> Result> { - let tcx = infcx.tcx; +impl<'a, 'gcx, 'tcx> Layout { + pub fn compute_uncached(ty: Ty<'gcx>, + infcx: &InferCtxt<'a, 'gcx, 'tcx>) + -> Result> { + let tcx = infcx.tcx.global_tcx(); let dl = &tcx.data_layout; assert!(!ty.has_infer_types()); @@ -1220,10 +1220,10 @@ pub enum SizeSkeleton<'tcx> { } } -impl<'a, 'tcx> SizeSkeleton<'tcx> { - pub fn compute(ty: Ty<'tcx>, infcx: &InferCtxt<'a, 'tcx, 'tcx>) - -> Result, LayoutError<'tcx>> { - let tcx = infcx.tcx; +impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> { + pub fn compute(ty: Ty<'gcx>, infcx: &InferCtxt<'a, 'gcx, 'tcx>) + -> Result, LayoutError<'gcx>> { + let tcx = infcx.tcx.global_tcx(); assert!(!ty.has_infer_types()); // First try computing a static layout. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 7bede4889645..005d83da38db 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -165,8 +165,8 @@ pub struct ImplHeader<'tcx> { pub predicates: Vec>, } -impl<'a, 'tcx> ImplHeader<'tcx> { - pub fn with_fresh_ty_vars(selcx: &mut traits::SelectionContext<'a, 'tcx, 'tcx>, +impl<'a, 'gcx, 'tcx> ImplHeader<'tcx> { + pub fn with_fresh_ty_vars(selcx: &mut traits::SelectionContext<'a, 'gcx, 'tcx>, impl_def_id: DefId) -> ImplHeader<'tcx> { @@ -524,6 +524,10 @@ bitflags! { // that are local to a particular fn const HAS_LOCAL_NAMES = 1 << 9, + // Present if the type belongs in a local type context. + // Only set for TyInfer other than Fresh. + const KEEP_IN_LOCAL_TCX = 1 << 10, + const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | TypeFlags::HAS_SELF.bits | TypeFlags::HAS_RE_EARLY_BOUND.bits, @@ -540,7 +544,8 @@ bitflags! { TypeFlags::HAS_TY_ERR.bits | TypeFlags::HAS_PROJECTION.bits | TypeFlags::HAS_TY_CLOSURE.bits | - TypeFlags::HAS_LOCAL_NAMES.bits, + TypeFlags::HAS_LOCAL_NAMES.bits | + TypeFlags::KEEP_IN_LOCAL_TCX.bits, // Caches for type_is_sized, type_moves_by_default const SIZEDNESS_CACHED = 1 << 16, @@ -2715,15 +2720,33 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn closure_kind(self, def_id: DefId) -> ty::ClosureKind { - Tables::closure_kind(&self.tables, self.global_tcx(), def_id) + // If this is a local def-id, it should be inserted into the + // tables by typeck; else, it will be retreived from + // the external crate metadata. + if let Some(&kind) = self.tables.borrow().closure_kinds.get(&def_id) { + return kind; + } + + let kind = self.sess.cstore.closure_kind(def_id); + self.tables.borrow_mut().closure_kinds.insert(def_id, kind); + kind } pub fn closure_type(self, def_id: DefId, - substs: ClosureSubsts<'gcx>) - -> ty::ClosureTy<'gcx> + substs: ClosureSubsts<'tcx>) + -> ty::ClosureTy<'tcx> { - Tables::closure_type(&self.tables, self.global_tcx(), def_id, substs) + // If this is a local def-id, it should be inserted into the + // tables by typeck; else, it will be retreived from + // the external crate metadata. + if let Some(ty) = self.tables.borrow().closure_tys.get(&def_id) { + return ty.subst(self, substs.func_substs); + } + + let ty = self.sess.cstore.closure_ty(self.global_tcx(), def_id); + self.tables.borrow_mut().closure_tys.insert(def_id, ty.clone()); + ty.subst(self, substs.func_substs) } /// Given the def_id of an impl, return the def_id of the trait it implements. diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 284019ed6a29..77e980ff3196 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -131,6 +131,41 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> { } } +impl<'a, 'tcx> Lift<'tcx> for ty::Predicate<'a> { + type Lifted = ty::Predicate<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + match *self { + ty::Predicate::Trait(ref binder) => { + tcx.lift(binder).map(ty::Predicate::Trait) + } + ty::Predicate::Equate(ref binder) => { + tcx.lift(binder).map(ty::Predicate::Equate) + } + ty::Predicate::RegionOutlives(ref binder) => { + tcx.lift(binder).map(ty::Predicate::RegionOutlives) + } + ty::Predicate::TypeOutlives(ref binder) => { + tcx.lift(binder).map(ty::Predicate::TypeOutlives) + } + ty::Predicate::Projection(ref binder) => { + tcx.lift(binder).map(ty::Predicate::Projection) + } + ty::Predicate::WellFormed(ty) => { + tcx.lift(&ty).map(ty::Predicate::WellFormed) + } + ty::Predicate::Rfc1592(box ref a) => { + tcx.lift(a).map(|a| ty::Predicate::Rfc1592(Box::new(a))) + } + ty::Predicate::ClosureKind(closure_def_id, kind) => { + Some(ty::Predicate::ClosureKind(closure_def_id, kind)) + } + ty::Predicate::ObjectSafe(trait_def_id) => { + Some(ty::Predicate::ObjectSafe(trait_def_id)) + } + } + } +} + impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder { type Lifted = ty::Binder; fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 4b96527cbe17..08909861d3f6 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -134,9 +134,9 @@ impl<'tcx> ParameterEnvironment<'tcx> { self_type: Ty<'tcx>, span: Span) -> Result<(),CopyImplementationError> { // FIXME: (@jroesch) float this code up - let adt = InferCtxt::enter(tcx, None, Some(self.clone()), - ProjectionMode::Topmost, |infcx| { - match self_type.sty { + tcx.infer_ctxt(None, Some(self.clone()), + ProjectionMode::Topmost).enter(|infcx| { + let adt = match self_type.sty { ty::TyStruct(struct_def, substs) => { for field in struct_def.all_fields() { let field_ty = field.ty(tcx, substs); @@ -145,7 +145,7 @@ impl<'tcx> ParameterEnvironment<'tcx> { field.name)) } } - Ok(struct_def) + struct_def } ty::TyEnum(enum_def, substs) => { for variant in &enum_def.variants { @@ -157,17 +157,17 @@ impl<'tcx> ParameterEnvironment<'tcx> { } } } - Ok(enum_def) + enum_def } - _ => Err(CopyImplementationError::NotAnAdt) + _ => return Err(CopyImplementationError::NotAnAdt) + }; + + if adt.has_dtor() { + return Err(CopyImplementationError::HasDestructor); } - })?; - if adt.has_dtor() { - return Err(CopyImplementationError::HasDestructor) - } - - Ok(()) + Ok(()) + }) } } @@ -513,7 +513,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { param_env: &ParameterEnvironment<'tcx>, bound: ty::BuiltinBound, span: Span) -> bool { - InferCtxt::enter(tcx, None, Some(param_env.clone()), ProjectionMode::Topmost, |infcx| { + tcx.infer_ctxt(None, Some(param_env.clone()), ProjectionMode::Topmost).enter(|infcx| { traits::type_known_to_meet_builtin_bound(&infcx, self, bound, span) }) } @@ -596,19 +596,20 @@ impl<'a, 'tcx> ty::TyS<'tcx> { } #[inline] - pub fn layout(&'tcx self, infcx: &InferCtxt<'a, 'tcx, 'tcx>) - -> Result<&'tcx Layout, LayoutError<'tcx>> { + pub fn layout<'lcx>(&'tcx self, infcx: &InferCtxt<'a, 'tcx, 'lcx>) + -> Result<&'tcx Layout, LayoutError<'tcx>> { + let tcx = infcx.tcx.global_tcx(); let can_cache = !self.has_param_types() && !self.has_self_ty(); if can_cache { - if let Some(&cached) = infcx.tcx.layout_cache.borrow().get(&self) { + if let Some(&cached) = tcx.layout_cache.borrow().get(&self) { return Ok(cached); } } let layout = Layout::compute_uncached(self, infcx)?; - let layout = infcx.tcx.intern_layout(layout); + let layout = tcx.intern_layout(layout); if can_cache { - infcx.tcx.layout_cache.borrow_mut().insert(self, layout); + tcx.layout_cache.borrow_mut().insert(self, layout); } Ok(layout) } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index ff22db4ccda4..1a802064b612 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -69,12 +69,12 @@ pub enum Ns { Value } -fn number_of_supplied_defaults<'a, 'tcx, GG>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - substs: &subst::Substs, - space: subst::ParamSpace, - get_generics: GG) - -> usize - where GG: FnOnce(TyCtxt<'a, 'tcx, 'tcx>) -> ty::Generics<'tcx> +fn number_of_supplied_defaults<'a, 'gcx, 'tcx, GG>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + substs: &subst::Substs, + space: subst::ParamSpace, + get_generics: GG) + -> usize + where GG: FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> ty::Generics<'tcx> { let generics = get_generics(tcx); @@ -115,7 +115,7 @@ pub fn parameterized(f: &mut fmt::Formatter, projections: &[ty::ProjectionPredicate], get_generics: GG) -> fmt::Result - where GG: for<'a, 'tcx> FnOnce(TyCtxt<'a, 'tcx, 'tcx>) -> ty::Generics<'tcx> + where GG: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> ty::Generics<'tcx> { if let (Ns::Value, Some(self_ty)) = (ns, substs.self_ty()) { write!(f, "<{} as ", self_ty)?; @@ -231,10 +231,10 @@ pub fn parameterized(f: &mut fmt::Formatter, Ok(()) } -fn in_binder<'a, 'tcx, T, U>(f: &mut fmt::Formatter, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - original: &ty::Binder, - lifted: Option>) -> fmt::Result +fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + original: &ty::Binder, + lifted: Option>) -> fmt::Result where T: fmt::Display, U: fmt::Display + TypeFoldable<'tcx> { // Replace any anonymous late-bound regions with named diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index c5fe43666219..bf5bce8fc3ba 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -22,12 +22,10 @@ use borrowck::*; use borrowck::InteriorKind::{InteriorElement, InteriorField}; use rustc::middle::expr_use_visitor as euv; use rustc::middle::expr_use_visitor::MutateMode; -use rustc::infer::InferCtxt; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; use rustc::middle::region; use rustc::ty::{self, TyCtxt}; -use rustc::traits::ProjectionMode; use syntax::ast; use syntax::codemap::Span; use rustc::hir; @@ -203,17 +201,15 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, debug!("check_loans(body id={})", body.id); let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); - InferCtxt::enter(bccx.tcx, None, Some(param_env), ProjectionMode::AnyFinal, |infcx| { - let mut clcx = CheckLoanCtxt { - bccx: bccx, - dfcx_loans: dfcx_loans, - move_data: move_data, - all_loans: all_loans, - param_env: &infcx.parameter_environment - }; - let mut euv = euv::ExprUseVisitor::new(&mut clcx, &infcx); - euv.walk_fn(decl, body); - }); + let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env); + let mut clcx = CheckLoanCtxt { + bccx: bccx, + dfcx_loans: dfcx_loans, + move_data: move_data, + all_loans: all_loans, + param_env: &infcx.parameter_environment + }; + euv::ExprUseVisitor::new(&mut clcx, &infcx).walk_fn(decl, body); } #[derive(PartialEq)] diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index b4d7ca6627e7..7d4f02bfe110 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -19,12 +19,10 @@ use borrowck::*; use borrowck::move_data::MoveData; use rustc::middle::expr_use_visitor as euv; -use rustc::infer::InferCtxt; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; use rustc::middle::region; use rustc::ty::{self, TyCtxt}; -use rustc::traits::ProjectionMode; use syntax::ast; use syntax::codemap::Span; @@ -56,10 +54,8 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, }; let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); - InferCtxt::enter(bccx.tcx, None, Some(param_env), ProjectionMode::AnyFinal, |infcx| { - let mut euv = euv::ExprUseVisitor::new(&mut glcx, &infcx); - euv.walk_fn(decl, body); - }); + let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env); + euv::ExprUseVisitor::new(&mut glcx, &infcx).walk_fn(decl, body); glcx.report_potential_errors(); let GatherLoanCtxt { all_loans, move_data, .. } = glcx; @@ -520,21 +516,22 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { /// sure the loans being taken are sound. struct StaticInitializerCtxt<'a, 'tcx: 'a> { bccx: &'a BorrowckCtxt<'a, 'tcx>, + item_id: ast::NodeId } impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> { fn visit_expr(&mut self, ex: &Expr) { if let hir::ExprAddrOf(mutbl, ref base) = ex.node { - let err = InferCtxt::enter(self.bccx.tcx, None, None, - ProjectionMode::AnyFinal, |infcx| { - let mc = mc::MemCategorizationContext::new(&infcx); - let base_cmt = mc.cat_expr(&base).unwrap(); - let borrow_kind = ty::BorrowKind::from_mutbl(mutbl); - // Check that we don't allow borrows of unsafe static items. - check_aliasability(self.bccx, ex.span, - BorrowViolation(euv::AddrOf), - base_cmt, borrow_kind).is_err() - }); + let param_env = ty::ParameterEnvironment::for_item(self.bccx.tcx, + self.item_id); + let infcx = self.bccx.tcx.borrowck_fake_infer_ctxt(param_env); + let mc = mc::MemCategorizationContext::new(&infcx); + let base_cmt = mc.cat_expr(&base).unwrap(); + let borrow_kind = ty::BorrowKind::from_mutbl(mutbl); + // Check that we don't allow borrows of unsafe static items. + let err = check_aliasability(self.bccx, ex.span, + BorrowViolation(euv::AddrOf), + base_cmt, borrow_kind).is_err(); if err { return; // reported an error, no sense in reporting more. } @@ -544,12 +541,15 @@ impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> { } } -pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt, expr: &hir::Expr) { +pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt, + item_id: ast::NodeId, + expr: &hir::Expr) { debug!("gather_loans_in_static_initializer(expr={:?})", expr); let mut sicx = StaticInitializerCtxt { - bccx: bccx + bccx: bccx, + item_id: item_id }; sicx.visit_expr(expr); diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index ca6d00a2baf3..f0ea69c8a6b3 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -87,14 +87,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for BorrowckCtxt<'a, 'tcx> { fn visit_trait_item(&mut self, ti: &hir::TraitItem) { if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node { - gather_loans::gather_loans_in_static_initializer(self, &expr); + gather_loans::gather_loans_in_static_initializer(self, ti.id, &expr); } intravisit::walk_trait_item(self, ti); } fn visit_impl_item(&mut self, ii: &hir::ImplItem) { if let hir::ImplItemKind::Const(_, ref expr) = ii.node { - gather_loans::gather_loans_in_static_initializer(self, &expr); + gather_loans::gather_loans_in_static_initializer(self, ii.id, &expr); } intravisit::walk_impl_item(self, ii); } @@ -142,7 +142,7 @@ fn borrowck_item(this: &mut BorrowckCtxt, item: &hir::Item) { match item.node { hir::ItemStatic(_, _, ref ex) | hir::ItemConst(_, ref ex) => { - gather_loans::gather_loans_in_static_initializer(this, &ex); + gather_loans::gather_loans_in_static_initializer(this, item.id, &ex); } _ => { } } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index d7c1c877c8bf..61d2408d5bfb 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -22,7 +22,6 @@ use rustc::hir::def_id::{DefId}; use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor}; use rustc::middle::expr_use_visitor::{LoanCause, MutateMode}; use rustc::middle::expr_use_visitor as euv; -use rustc::infer::InferCtxt; use rustc::middle::mem_categorization::{cmt}; use rustc::hir::pat_util::*; use rustc::traits::ProjectionMode; @@ -1123,8 +1122,8 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, PatKind::Ident(hir::BindByValue(_), _, ref sub) => { let pat_ty = tcx.node_id_to_type(p.id); //FIXME: (@jroesch) this code should be floated up as well - InferCtxt::enter(cx.tcx, None, Some(cx.param_env.clone()), - ProjectionMode::AnyFinal, |infcx| { + cx.tcx.infer_ctxt(None, Some(cx.param_env.clone()), + ProjectionMode::AnyFinal).enter(|infcx| { if infcx.type_moves_by_default(pat_ty, pat.span) { check_move(p, sub.as_ref().map(|p| &**p)); } @@ -1150,8 +1149,8 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, /// assign. fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>, guard: &hir::Expr) { - InferCtxt::enter(cx.tcx, None, Some(cx.param_env.clone()), - ProjectionMode::AnyFinal, |infcx| { + cx.tcx.infer_ctxt(None, Some(cx.param_env.clone()), + ProjectionMode::AnyFinal).enter(|infcx| { let mut checker = MutationChecker { cx: cx, }; @@ -1160,11 +1159,11 @@ fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>, }); } -struct MutationChecker<'a, 'tcx: 'a> { - cx: &'a MatchCheckCtxt<'a, 'tcx>, +struct MutationChecker<'a, 'gcx: 'a> { + cx: &'a MatchCheckCtxt<'a, 'gcx>, } -impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> { +impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> { fn matched_pat(&mut self, _: &Pat, _: cmt, _: euv::MatchMode) {} fn consume(&mut self, _: NodeId, _: Span, _: cmt, _: ConsumeMode) {} fn consume_pat(&mut self, _: &Pat, _: cmt, _: ConsumeMode) {} diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 22ffebc081bb..9db24fa4770f 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -19,7 +19,6 @@ use rustc::hir::map as ast_map; use rustc::hir::map::blocks::FnLikeNode; use rustc::middle::cstore::{self, InlinedItem}; use rustc::traits; -use rustc::infer::InferCtxt; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::hir::pat_util::def_to_path; @@ -1014,7 +1013,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_ref); tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id()); - InferCtxt::enter(tcx, None, None, ProjectionMode::AnyFinal, |infcx| { + tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), trait_ref.to_poly_trait_predicate()); diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index fc44f808e4bf..9bbf250b9714 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -42,8 +42,8 @@ use syntax::feature_gate::UnstableFeatures; use rustc::hir; -struct Env<'a, 'tcx: 'a> { - infcx: &'a infer::InferCtxt<'a, 'tcx, 'tcx>, +struct Env<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + infcx: &'a infer::InferCtxt<'a, 'gcx, 'tcx>, } struct RH<'a> { @@ -149,7 +149,7 @@ fn test_env(source_string: &str, index, "test_crate", |tcx| { - InferCtxt::enter(tcx, None, None, ProjectionMode::AnyFinal, |infcx| { + tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| { body(Env { infcx: &infcx }); let free_regions = FreeRegionMap::new(); @@ -159,8 +159,8 @@ fn test_env(source_string: &str, }); } -impl<'a, 'tcx> Env<'a, 'tcx> { - pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { +impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { + pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.infcx.tcx } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 13cfa2a604d3..d1eba5b3f4a4 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -32,7 +32,6 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use middle::stability; use rustc::cfg; -use rustc::infer::InferCtxt; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::adjustment; @@ -866,7 +865,7 @@ impl LateLintPass for UnconditionalRecursion { let node_id = tcx.map.as_local_node_id(method.def_id).unwrap(); let param_env = Some(ty::ParameterEnvironment::for_item(tcx, node_id)); - InferCtxt::enter(tcx, None, param_env, ProjectionMode::AnyFinal, |infcx| { + tcx.infer_ctxt(None, param_env, ProjectionMode::AnyFinal).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/block.rs b/src/librustc_mir/build/block.rs index 3bfea6149193..c1626b93f0c4 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -13,7 +13,7 @@ use hair::*; use rustc::mir::repr::*; use rustc::hir; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn ast_block(&mut self, destination: &Lvalue<'tcx>, // FIXME(#32959): temporary measure for the issue diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index d97245a5fc21..a08d14d9e205 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -14,7 +14,7 @@ use build::Builder; use hair::*; use rustc::mir::repr::*; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Compile `expr`, yielding a compile-time constant. Assumes that /// `expr` is a valid compile-time constant! pub fn as_constant(&mut self, expr: M) -> Constant<'tcx> diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index 0c9323f4af37..15ea3f0e6e86 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -15,7 +15,7 @@ use build::expr::category::Category; use hair::*; use rustc::mir::repr::*; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Compile `expr`, yielding an lvalue that we can move from etc. pub fn as_lvalue(&mut self, block: BasicBlock, diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index 661d01ce989c..a059f2bdde9c 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -15,7 +15,7 @@ use build::expr::category::Category; use hair::*; use rustc::mir::repr::*; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Compile `expr` into a value that can be used as an operand. /// If `expr` is an lvalue like `x`, this will introduce a /// temporary `tmp = x`, so that we capture the value of `x` at diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 88757c6873c5..2a7334624089 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -17,7 +17,7 @@ use build::expr::category::{Category, RvalueFunc}; use hair::*; use rustc::mir::repr::*; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Compile `expr`, yielding an rvalue. pub fn as_rvalue(&mut self, block: BasicBlock, expr: M) -> BlockAnd> where M: Mirror<'tcx, Output = Expr<'tcx>> diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index a4f4e44b1b13..38d32ec6777e 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -15,7 +15,7 @@ use build::expr::category::Category; use hair::*; use rustc::mir::repr::*; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Compile `expr` into a fresh temporary. This is used when building /// up rvalues so as to freeze the value that will be consumed. pub fn as_temp(&mut self, block: BasicBlock, expr: M) -> BlockAnd> diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index efffde919100..41610c90377b 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -16,7 +16,7 @@ use hair::*; use rustc::ty; use rustc::mir::repr::*; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Compile `expr`, storing the result into `destination`, which /// is assumed to be uninitialized. pub fn into_expr(&mut self, diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index 3c1672b91975..9629396f48b5 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -15,7 +15,7 @@ use rustc::middle::region::CodeExtent; use rustc::mir::repr::*; use syntax::codemap::Span; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd<()> { let this = self; diff --git a/src/librustc_mir/build/into.rs b/src/librustc_mir/build/into.rs index 77d9d926328f..17ccb701c2b7 100644 --- a/src/librustc_mir/build/into.rs +++ b/src/librustc_mir/build/into.rs @@ -19,14 +19,14 @@ use hair::*; use rustc::mir::repr::*; pub trait EvalInto<'tcx> { - fn eval_into<'a>(self, - builder: &mut Builder<'a, 'tcx>, - destination: &Lvalue<'tcx>, - block: BasicBlock) - -> BlockAnd<()>; + fn eval_into<'a, 'gcx>(self, + builder: &mut Builder<'a, 'gcx, 'tcx>, + destination: &Lvalue<'tcx>, + block: BasicBlock) + -> BlockAnd<()>; } -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn into(&mut self, destination: &Lvalue<'tcx>, block: BasicBlock, @@ -39,22 +39,22 @@ impl<'a,'tcx> Builder<'a,'tcx> { } impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> { - fn eval_into<'a>(self, - builder: &mut Builder<'a, 'tcx>, - destination: &Lvalue<'tcx>, - block: BasicBlock) - -> BlockAnd<()> { + fn eval_into<'a, 'gcx>(self, + builder: &mut Builder<'a, 'gcx, 'tcx>, + destination: &Lvalue<'tcx>, + block: BasicBlock) + -> BlockAnd<()> { let expr = builder.hir.mirror(self); builder.into_expr(destination, block, expr) } } impl<'tcx> EvalInto<'tcx> for Expr<'tcx> { - fn eval_into<'a>(self, - builder: &mut Builder<'a, 'tcx>, - destination: &Lvalue<'tcx>, - block: BasicBlock) - -> BlockAnd<()> { + fn eval_into<'a, 'gcx>(self, + builder: &mut Builder<'a, 'gcx, 'tcx>, + destination: &Lvalue<'tcx>, + block: BasicBlock) + -> BlockAnd<()> { builder.into_expr(destination, block, self) } } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 080183ae1da6..c1a0e1f9a690 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -27,7 +27,7 @@ mod simplify; mod test; mod util; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn match_expr(&mut self, destination: &Lvalue<'tcx>, span: Span, @@ -304,7 +304,7 @@ pub struct Test<'tcx> { /////////////////////////////////////////////////////////////////////////// // Main matching algorithm -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// The main match algorithm. It begins with a set of candidates /// `candidates` and has the job of generating code to determine /// which of these candidates, if any, is the correct one. The diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index a3337badf884..c707bb8a27b6 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -29,7 +29,7 @@ use rustc::mir::repr::*; use std::mem; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn simplify_candidate<'pat>(&mut self, mut block: BasicBlock, candidate: &mut Candidate<'pat, 'tcx>) diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index f70d4321a49b..e53584a3f8b1 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -24,7 +24,7 @@ use rustc::ty::{self, Ty}; use rustc::mir::repr::*; use syntax::codemap::Span; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Identifies what test is needed to decide if `match_pair` is applicable. /// /// It is a bug to call this with a simplifyable pattern. diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir/build/matches/util.rs index e5f2c7543786..5eb58f7612d7 100644 --- a/src/librustc_mir/build/matches/util.rs +++ b/src/librustc_mir/build/matches/util.rs @@ -14,7 +14,7 @@ use hair::*; use rustc::mir::repr::*; use std::u32; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn field_match_pairs<'pat>(&mut self, lvalue: Lvalue<'tcx>, subpatterns: &'pat [FieldPattern<'tcx>]) diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 5daaf37d8781..7317c6f9b313 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -17,7 +17,7 @@ use rustc::mir::repr::*; use std::u32; use syntax::codemap::Span; -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Add a new temporary value of type `ty` storing the result of /// evaluating `expr`. /// diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index ac64d1eb65b4..77499a0f96cd 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -21,8 +21,8 @@ use syntax::ast; use syntax::codemap::Span; use syntax::parse::token::keywords; -pub struct Builder<'a, 'tcx: 'a> { - hir: Cx<'a, 'tcx, 'tcx>, +pub struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + hir: Cx<'a, 'gcx, 'tcx>, cfg: CFG<'tcx>, fn_span: Span, @@ -160,13 +160,13 @@ macro_rules! unpack { /////////////////////////////////////////////////////////////////////////// /// the main entry point for building MIR for a function -pub fn construct_fn<'a, 'tcx, A>(hir: Cx<'a, 'tcx, 'tcx>, - fn_id: ast::NodeId, - arguments: A, - return_ty: ty::FnOutput<'tcx>, - ast_block: &'tcx hir::Block) - -> (Mir<'tcx>, ScopeAuxiliaryVec) - where A: Iterator, Option<&'tcx hir::Pat>)> +pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, + fn_id: ast::NodeId, + arguments: A, + return_ty: ty::FnOutput<'gcx>, + ast_block: &'gcx hir::Block) + -> (Mir<'tcx>, ScopeAuxiliaryVec) + where A: Iterator, Option<&'gcx hir::Pat>)> { let tcx = hir.tcx(); let span = tcx.map.span(fn_id); @@ -232,10 +232,10 @@ pub fn construct_fn<'a, 'tcx, A>(hir: Cx<'a, 'tcx, 'tcx>, builder.finish(upvar_decls, arg_decls, return_ty) } -pub fn construct_const<'a, 'tcx>(hir: Cx<'a, 'tcx, 'tcx>, - item_id: ast::NodeId, - ast_expr: &'tcx hir::Expr) - -> (Mir<'tcx>, ScopeAuxiliaryVec) { +pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, + item_id: ast::NodeId, + ast_expr: &'tcx hir::Expr) + -> (Mir<'tcx>, ScopeAuxiliaryVec) { let tcx = hir.tcx(); let span = tcx.map.span(item_id); let mut builder = Builder::new(hir, span); @@ -259,8 +259,8 @@ pub fn construct_const<'a, 'tcx>(hir: Cx<'a, 'tcx, 'tcx>, builder.finish(vec![], vec![], ty::FnConverging(ty)) } -impl<'a,'tcx> Builder<'a,'tcx> { - fn new(hir: Cx<'a, 'tcx, 'tcx>, span: Span) -> Builder<'a, 'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { + fn new(hir: Cx<'a, 'gcx, 'tcx>, span: Span) -> Builder<'a, 'gcx, 'tcx> { let mut builder = Builder { hir: hir, cfg: CFG { basic_blocks: vec![] }, @@ -311,9 +311,9 @@ impl<'a,'tcx> Builder<'a,'tcx> { return_ty: ty::FnOutput<'tcx>, arguments: A, argument_scope_id: ScopeId, - ast_block: &'tcx hir::Block) + ast_block: &'gcx hir::Block) -> BlockAnd>> - where A: Iterator, Option<&'tcx hir::Pat>)> + where A: Iterator, Option<&'gcx hir::Pat>)> { // to start, translate the argument patterns and collect the argument types. let arg_decls = arguments.enumerate().map(|(index, (ty, pattern))| { diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index d07a58b981b9..071c8d618c84 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -206,7 +206,7 @@ impl<'tcx> Scope<'tcx> { } } -impl<'a,'tcx> Builder<'a,'tcx> { +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Adding and removing scopes // ========================== /// Start a loop scope, which tracks where `continue` and `break` @@ -218,7 +218,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { break_block: BasicBlock, f: F) -> bool - where F: FnOnce(&mut Builder<'a, 'tcx>) + where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) { let extent = self.extent_of_innermost_scope(); let loop_scope = LoopScope { @@ -237,7 +237,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { /// Convenience wrapper that pushes a scope and then executes `f` /// to build its contents, popping the scope afterwards. pub fn in_scope(&mut self, extent: CodeExtent, mut block: BasicBlock, f: F) -> BlockAnd - where F: FnOnce(&mut Builder<'a, 'tcx>, ScopeId) -> BlockAnd + where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>, ScopeId) -> BlockAnd { debug!("in_scope(extent={:?}, block={:?})", extent, block); let id = self.push_scope(extent, block); @@ -662,12 +662,12 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>, block.unit() } -fn build_diverge_scope<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - cfg: &mut CFG<'tcx>, - unit_temp: &Lvalue<'tcx>, - scope: &mut Scope<'tcx>, - mut target: BasicBlock) - -> BasicBlock +fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + cfg: &mut CFG<'tcx>, + unit_temp: &Lvalue<'tcx>, + scope: &mut Scope<'tcx>, + mut target: BasicBlock) + -> BasicBlock { // Build up the drops in **reverse** order. The end result will // look like: @@ -721,11 +721,11 @@ fn build_diverge_scope<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, target } -fn build_free<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - unit_temp: &Lvalue<'tcx>, - data: &FreeData<'tcx>, - target: BasicBlock) - -> TerminatorKind<'tcx> { +fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + unit_temp: &Lvalue<'tcx>, + data: &FreeData<'tcx>, + target: BasicBlock) + -> TerminatorKind<'tcx> { let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) .unwrap_or_else(|e| tcx.sess.fatal(&e)); let substs = tcx.mk_substs(Substs::new( diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index fd568aebea43..52d54f2cc857 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -18,7 +18,7 @@ use syntax::ast; impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { type Output = Block<'tcx>; - fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx, 'tcx>) -> Block<'tcx> { + fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> { // We have to eagerly translate the "spine" of the statements // in order to get the lexical scoping correctly. let stmts = mirror_stmts(cx, self.id, &*self.stmts); @@ -31,10 +31,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { } } -fn mirror_stmts<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, - block_id: ast::NodeId, - stmts: &'tcx [hir::Stmt]) - -> Vec> +fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, + block_id: ast::NodeId, + stmts: &'tcx [hir::Stmt]) + -> Vec> { let mut result = vec![]; for (index, stmt) in stmts.iter().enumerate() { @@ -74,9 +74,9 @@ fn mirror_stmts<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, return result; } -pub fn to_expr_ref<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, - block: &'tcx hir::Block) - -> ExprRef<'tcx> { +pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, + block: &'tcx hir::Block) + -> ExprRef<'tcx> { let block_ty = cx.tcx.node_id_to_type(block.id); let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id); let expr = Expr { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 39e9ace5432a..1e7164a62c07 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -29,7 +29,7 @@ use syntax::ptr::P; impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { type Output = Expr<'tcx>; - fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx, 'tcx>) -> Expr<'tcx> { + fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> { let temp_lifetime = cx.tcx.region_maps.temporary_scope(self.id); let expr_extent = cx.tcx.region_maps.node_extent(self.id); @@ -202,9 +202,9 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { } } -fn make_mirror_unadjusted<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, - expr: &'tcx hir::Expr) - -> Expr<'tcx> { +fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, + expr: &'tcx hir::Expr) + -> Expr<'tcx> { let expr_ty = cx.tcx.expr_ty(expr); let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); @@ -545,7 +545,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, count: TypedConstVal { ty: cx.tcx.expr_ty(c), span: c.span, - value: match const_eval::eval_const_expr(cx.tcx, c) { + value: match const_eval::eval_const_expr(cx.tcx.global_tcx(), c) { ConstVal::Integral(ConstInt::Usize(u)) => u, other => bug!("constant evaluation of repeat count yielded {:?}", other), }, @@ -622,10 +622,10 @@ fn make_mirror_unadjusted<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, } } -fn method_callee<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, - expr: &hir::Expr, - method_call: ty::MethodCall) - -> Expr<'tcx> { +fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, + expr: &hir::Expr, + method_call: ty::MethodCall) + -> Expr<'tcx> { let tables = cx.tcx.tables.borrow(); let callee = &tables.method_map[&method_call]; let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); @@ -649,8 +649,8 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind { } } -fn convert_arm<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, - arm: &'tcx hir::Arm) -> Arm<'tcx> { +fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, + arm: &'tcx hir::Arm) -> Arm<'tcx> { let mut map; let opt_map = if arm.pats.len() == 1 { None @@ -669,9 +669,9 @@ fn convert_arm<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, } } -fn convert_path_expr<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, - expr: &'tcx hir::Expr) - -> ExprKind<'tcx> { +fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, + expr: &'tcx hir::Expr) + -> ExprKind<'tcx> { let substs = cx.tcx.node_id_item_substs(expr.id).substs; // Otherwise there may be def_map borrow conflicts let def = cx.tcx.def_map.borrow()[&expr.id].full_def(); @@ -714,7 +714,8 @@ fn convert_path_expr<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, Def::Const(def_id) | Def::AssociatedConst(def_id) => { let substs = Some(cx.tcx.node_id_item_substs(expr.id).substs); - if let Some((e, _)) = const_eval::lookup_const_by_id(cx.tcx, def_id, substs) { + let tcx = cx.tcx.global_tcx(); + if let Some((e, _)) = const_eval::lookup_const_by_id(tcx, def_id, substs) { // FIXME ConstVal can't be yet used with adjustments, as they would be lost. if !cx.tcx.tables.borrow().adjustments.contains_key(&e.id) { if let Some(v) = cx.try_const_eval_literal(e) { @@ -743,10 +744,10 @@ fn convert_path_expr<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, } } -fn convert_var<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, - expr: &'tcx hir::Expr, - def: Def) - -> ExprKind<'tcx> { +fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, + expr: &'tcx hir::Expr, + def: Def) + -> ExprKind<'tcx> { let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); match def { @@ -908,13 +909,13 @@ enum PassArgs { ByRef, } -fn overloaded_operator<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, - expr: &'tcx hir::Expr, - method_call: ty::MethodCall, - pass_args: PassArgs, - receiver: ExprRef<'tcx>, - args: Vec<&'tcx P>) - -> ExprKind<'tcx> { +fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, + expr: &'tcx hir::Expr, + method_call: ty::MethodCall, + pass_args: PassArgs, + receiver: ExprRef<'tcx>, + args: Vec<&'tcx P>) + -> ExprKind<'tcx> { // the receiver has all the adjustments that are needed, so we can // just push a reference to it let mut argrefs = vec![receiver]; @@ -959,13 +960,13 @@ fn overloaded_operator<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, } } -fn overloaded_lvalue<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, - expr: &'tcx hir::Expr, - method_call: ty::MethodCall, - pass_args: PassArgs, - receiver: ExprRef<'tcx>, - args: Vec<&'tcx P>) - -> ExprKind<'tcx> { +fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, + expr: &'tcx hir::Expr, + method_call: ty::MethodCall, + pass_args: PassArgs, + receiver: ExprRef<'tcx>, + args: Vec<&'tcx P>) + -> ExprKind<'tcx> { // For an overloaded *x or x[y] expression of type T, the method // call returns an &T and we must add the deref so that the types // line up (this is because `*x` and `x[y]` represent lvalues): @@ -994,11 +995,11 @@ fn overloaded_lvalue<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, ExprKind::Deref { arg: ref_expr.to_ref() } } -fn capture_freevar<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, - closure_expr: &'tcx hir::Expr, - freevar: &hir::Freevar, - freevar_ty: Ty<'tcx>) - -> ExprRef<'tcx> { +fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, + closure_expr: &'tcx hir::Expr, + freevar: &hir::Freevar, + freevar_ty: Ty<'tcx>) + -> ExprRef<'tcx> { let id_var = freevar.def.var_id(); let upvar_id = ty::UpvarId { var_id: id_var, @@ -1035,8 +1036,8 @@ fn capture_freevar<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, } } -fn loop_label<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>, - expr: &'tcx hir::Expr) -> CodeExtent { +fn loop_label<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, + expr: &'tcx hir::Expr) -> CodeExtent { match cx.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) { Some(Def::Label(loop_id)) => cx.tcx.region_maps.node_extent(loop_id), d => { diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 8f79b6e68eee..fad6cfb7ae1a 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -35,10 +35,10 @@ pub struct Cx<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { constness: hir::Constness } -impl<'a, 'tcx> Cx<'a, 'tcx, 'tcx> { - pub fn new(infcx: &'a InferCtxt<'a, 'tcx, 'tcx>, +impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { + pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, constness: hir::Constness) - -> Cx<'a, 'tcx, 'tcx> { + -> Cx<'a, 'gcx, 'tcx> { Cx { tcx: infcx.tcx, infcx: infcx, @@ -47,7 +47,7 @@ impl<'a, 'tcx> Cx<'a, 'tcx, 'tcx> { } } -impl<'a, 'tcx: 'a> Cx<'a, 'tcx, 'tcx> { +impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { /// Normalizes `ast` into the appropriate `mirror` type. pub fn mirror>(&mut self, ast: M) -> M::Output { ast.make_mirror(self) @@ -85,12 +85,15 @@ impl<'a, 'tcx: 'a> Cx<'a, 'tcx, 'tcx> { } pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> { - Literal::Value { value: const_eval::eval_const_expr(self.tcx, e) } + Literal::Value { + value: const_eval::eval_const_expr(self.tcx.global_tcx(), e) + } } pub fn try_const_eval_literal(&mut self, e: &hir::Expr) -> Option> { let hint = const_eval::EvalHint::ExprTypeChecked; - const_eval::eval_const_expr_partial(self.tcx, e, hint, None).ok().and_then(|v| { + let tcx = self.tcx.global_tcx(); + const_eval::eval_const_expr_partial(tcx, e, hint, None).ok().and_then(|v| { match v { // All of these contain local IDs, unsuitable for storing in MIR. ConstVal::Struct(_) | ConstVal::Tuple(_) | @@ -130,21 +133,25 @@ impl<'a, 'tcx: 'a> Cx<'a, 'tcx, 'tcx> { bug!("found no method `{}` in `{:?}`", method_name, trait_def_id); } - pub fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize { + pub fn num_variants(&mut self, adt_def: ty::AdtDef) -> usize { adt_def.variants.len() } - pub fn all_fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec { + pub fn all_fields(&mut self, adt_def: ty::AdtDef, variant_index: usize) -> Vec { (0..adt_def.variants[variant_index].fields.len()) .map(Field::new) .collect() } pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool { + let ty = self.tcx.lift_to_global(&ty).unwrap_or_else(|| { + bug!("MIR: Cx::needs_drop({}) got \ + type with inference types/regions", ty); + }); self.tcx.type_needs_drop_given_env(ty, &self.infcx.parameter_environment) } - pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { + pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx } } diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index 3fbfead0c08d..9e08e7b62d3b 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -34,12 +34,12 @@ use syntax::ptr::P; /// _ => { ... } /// } /// ``` -struct PatCx<'patcx, 'cx: 'patcx, 'tcx: 'cx> { - cx: &'patcx mut Cx<'cx, 'tcx, 'tcx>, +struct PatCx<'patcx, 'cx: 'patcx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { + cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>, binding_map: Option<&'patcx FnvHashMap>, } -impl<'cx, 'tcx> Cx<'cx, 'tcx, 'tcx> { +impl<'cx, 'gcx, 'tcx> Cx<'cx, 'gcx, 'tcx> { pub fn irrefutable_pat(&mut self, pat: &hir::Pat) -> Pattern<'tcx> { PatCx::new(self, None).to_pattern(pat) } @@ -52,10 +52,10 @@ impl<'cx, 'tcx> Cx<'cx, 'tcx, 'tcx> { } } -impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> { - fn new(cx: &'patcx mut Cx<'cx, 'tcx, 'tcx>, +impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { + fn new(cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>, binding_map: Option<&'patcx FnvHashMap>) - -> PatCx<'patcx, 'cx, 'tcx> { + -> PatCx<'patcx, 'cx, 'gcx, 'tcx> { PatCx { cx: cx, binding_map: binding_map, @@ -69,14 +69,14 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> { PatKind::Wild => PatternKind::Wild, PatKind::Lit(ref value) => { - let value = const_eval::eval_const_expr(self.cx.tcx, value); + let value = const_eval::eval_const_expr(self.cx.tcx.global_tcx(), value); PatternKind::Constant { value: value } } PatKind::Range(ref lo, ref hi) => { - let lo = const_eval::eval_const_expr(self.cx.tcx, lo); + let lo = const_eval::eval_const_expr(self.cx.tcx.global_tcx(), lo); let lo = Literal::Value { value: lo }; - let hi = const_eval::eval_const_expr(self.cx.tcx, hi); + let hi = const_eval::eval_const_expr(self.cx.tcx.global_tcx(), hi); let hi = Literal::Value { value: hi }; PatternKind::Range { lo: lo, hi: hi } }, @@ -87,10 +87,11 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> { let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { + let tcx = self.cx.tcx.global_tcx(); let substs = Some(self.cx.tcx.node_id_item_substs(pat.id).substs); - match const_eval::lookup_const_by_id(self.cx.tcx, def_id, substs) { + match const_eval::lookup_const_by_id(tcx, def_id, substs) { Some((const_expr, _const_ty)) => { - match const_eval::const_expr_to_pat(self.cx.tcx, + match const_eval::const_expr_to_pat(tcx, const_expr, pat.id, pat.span) { diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 1cdf077ffac0..020fbb6fcd19 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -358,13 +358,13 @@ pub struct FieldPattern<'tcx> { pub trait Mirror<'tcx> { type Output; - fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx, 'tcx>) -> Self::Output; + fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Self::Output; } impl<'tcx> Mirror<'tcx> for Expr<'tcx> { type Output = Expr<'tcx>; - fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx, 'tcx>) -> Expr<'tcx> { + fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> { self } } @@ -372,7 +372,7 @@ impl<'tcx> Mirror<'tcx> for Expr<'tcx> { impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> { type Output = Expr<'tcx>; - fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx, 'tcx>) -> Expr<'tcx> { + fn make_mirror<'a, 'gcx>(self, hir: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> { match self { ExprRef::Hair(h) => h.make_mirror(hir), ExprRef::Mirror(m) => *m, @@ -383,7 +383,7 @@ impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> { impl<'tcx> Mirror<'tcx> for Stmt<'tcx> { type Output = Stmt<'tcx>; - fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx, 'tcx>) -> Stmt<'tcx> { + fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> { self } } @@ -391,7 +391,7 @@ impl<'tcx> Mirror<'tcx> for Stmt<'tcx> { impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> { type Output = Stmt<'tcx>; - fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx, 'tcx>) -> Stmt<'tcx> { + fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Stmt<'tcx> { match self { StmtRef::Mirror(m) => *m, } @@ -401,7 +401,7 @@ impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> { impl<'tcx> Mirror<'tcx> for Block<'tcx> { type Output = Block<'tcx>; - fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx, 'tcx>) -> Block<'tcx> { + fn make_mirror<'a, 'gcx>(self, _: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> { self } } diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 3874224e0541..73cfdeda74a8 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -20,13 +20,15 @@ use build; use rustc::dep_graph::DepNode; use rustc::mir::repr::Mir; use rustc::mir::transform::MirSource; +use rustc::mir::visit::MutVisitor; use pretty; use hair::cx::Cx; use rustc::mir::mir_map::MirMap; -use rustc::infer::InferCtxt; +use rustc::infer::InferCtxtBuilder; use rustc::traits::ProjectionMode; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::subst::Substs; use rustc::util::nodemap::NodeMap; use rustc::hir; use rustc::hir::intravisit::{self, FnKind, Visitor}; @@ -34,6 +36,8 @@ use rustc::hir::map::blocks::FnLikeNode; use syntax::ast; use syntax::codemap::Span; +use std::mem; + pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MirMap<'tcx> { let mut map = MirMap { map: NodeMap(), @@ -48,6 +52,36 @@ pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MirMap<'tcx map } +/// A pass to lift all the types and substitutions in a Mir +/// to the global tcx. Sadly, we don't have a "folder" that +/// can change 'tcx so we have to transmute afterwards. +struct GlobalizeMir<'a, 'gcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'gcx>, + span: Span +} + +impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> { + fn visit_ty(&mut self, ty: &mut Ty<'tcx>) { + if let Some(lifted) = self.tcx.lift(ty) { + *ty = lifted; + } else { + span_bug!(self.span, + "found type `{:?}` with inference types/regions in MIR", + ty); + } + } + + fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>) { + if let Some(lifted) = self.tcx.lift(substs) { + *substs = lifted; + } else { + span_bug!(self.span, + "found substs `{:?}` with inference types/regions in MIR", + substs); + } + } +} + /////////////////////////////////////////////////////////////////////////// // BuildMir -- walks a crate, looking for fn items and methods to build MIR from @@ -56,36 +90,69 @@ struct BuildMir<'a, 'tcx: 'a> { map: &'a mut MirMap<'tcx>, } -impl<'a, 'tcx> BuildMir<'a, 'tcx> { - fn build(&mut self, src: MirSource, f: F) - where F: for<'b> FnOnce(Cx<'b, 'tcx, 'tcx>) -> (Mir<'tcx>, build::ScopeAuxiliaryVec) - { - let constness = match src { - MirSource::Const(_) | - MirSource::Static(..) => hir::Constness::Const, - MirSource::Fn(id) => { - let fn_like = FnLikeNode::from_node(self.tcx.map.get(id)); - match fn_like.map(|f| f.kind()) { - Some(FnKind::ItemFn(_, _, _, c, _, _, _)) => c, - Some(FnKind::Method(_, m, _, _)) => m.constness, - _ => hir::Constness::NotConst - } - } - MirSource::Promoted(..) => bug!() - }; +/// Helper type of a temporary returned by BuildMir::cx(...). +/// Necessary because we can't write the following bound: +/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Cx<'b, 'gcx, 'tcx>). +struct CxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + src: MirSource, + infcx: InferCtxtBuilder<'a, 'gcx, 'tcx>, + map: &'a mut MirMap<'gcx>, +} +impl<'a, 'gcx, 'tcx> BuildMir<'a, 'gcx> { + fn cx<'b>(&'b mut self, src: MirSource) -> CxBuilder<'b, 'gcx, 'tcx> { let param_env = ty::ParameterEnvironment::for_item(self.tcx, src.item_id()); - let mir = InferCtxt::enter(self.tcx, None, Some(param_env), - ProjectionMode::AnyFinal, |infcx| { - let (mir, scope_auxiliary) = f(Cx::new(&infcx, constness)); - pretty::dump_mir(self.tcx, "mir_map", &0, src, &mir, Some(&scope_auxiliary)); + CxBuilder { + src: src, + infcx: self.tcx.infer_ctxt(None, Some(param_env), ProjectionMode::AnyFinal), + map: self.map + } + } +} + +impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> { + fn build(&'tcx mut self, f: F) + where F: for<'b> FnOnce(Cx<'b, 'gcx, 'tcx>) -> (Mir<'tcx>, build::ScopeAuxiliaryVec) + { + let src = self.src; + let mir = self.infcx.enter(|infcx| { + let constness = match src { + MirSource::Const(_) | + MirSource::Static(..) => hir::Constness::Const, + MirSource::Fn(id) => { + let fn_like = FnLikeNode::from_node(infcx.tcx.map.get(id)); + match fn_like.map(|f| f.kind()) { + Some(FnKind::ItemFn(_, _, _, c, _, _, _)) => c, + Some(FnKind::Method(_, m, _, _)) => m.constness, + _ => hir::Constness::NotConst + } + } + MirSource::Promoted(..) => bug!() + }; + let (mut mir, scope_auxiliary) = f(Cx::new(&infcx, constness)); + + // Convert the Mir to global types. + let mut globalizer = GlobalizeMir { + tcx: infcx.tcx.global_tcx(), + span: mir.span + }; + globalizer.visit_mir(&mut mir); + let mir = unsafe { + mem::transmute::>(mir) + }; + + pretty::dump_mir(infcx.tcx.global_tcx(), "mir_map", &0, + src, &mir, Some(&scope_auxiliary)); + mir }); assert!(self.map.map.insert(src.item_id(), mir).is_none()) } +} - fn build_const_integer(&mut self, expr: &'tcx hir::Expr) { +impl<'a, 'gcx> BuildMir<'a, 'gcx> { + fn build_const_integer(&mut self, expr: &'gcx hir::Expr) { // FIXME(eddyb) Closures should have separate // function definition IDs and expression IDs. // Type-checking should not let closures get @@ -93,7 +160,7 @@ impl<'a, 'tcx> BuildMir<'a, 'tcx> { if let hir::ExprClosure(..) = expr.node { return; } - self.build(MirSource::Const(expr.id), |cx| { + self.cx(MirSource::Const(expr.id)).build(|cx| { build::construct_const(cx, expr.id, expr) }); } @@ -104,12 +171,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { match item.node { hir::ItemConst(_, ref expr) => { - self.build(MirSource::Const(item.id), |cx| { + self.cx(MirSource::Const(item.id)).build(|cx| { build::construct_const(cx, item.id, expr) }); } hir::ItemStatic(_, m, ref expr) => { - self.build(MirSource::Static(item.id, m), |cx| { + self.cx(MirSource::Static(item.id, m)).build(|cx| { build::construct_const(cx, item.id, expr) }); } @@ -121,7 +188,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { // Trait associated const defaults. fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { if let hir::ConstTraitItem(_, Some(ref expr)) = item.node { - self.build(MirSource::Const(item.id), |cx| { + self.cx(MirSource::Const(item.id)).build(|cx| { build::construct_const(cx, item.id, expr) }); } @@ -131,7 +198,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { // Impl associated const. fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { if let hir::ImplItemKind::Const(_, ref expr) = item.node { - self.build(MirSource::Const(item.id), |cx| { + self.cx(MirSource::Const(item.id)).build(|cx| { build::construct_const(cx, item.id, expr) }); } @@ -192,8 +259,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { (fn_sig.inputs[index], Some(&*arg.pat)) }); - self.build(MirSource::Fn(id), |cx| { - let arguments = implicit_argument.into_iter().chain(explicit_arguments); + let arguments = implicit_argument.into_iter().chain(explicit_arguments); + self.cx(MirSource::Fn(id)).build(|cx| { build::construct_fn(cx, id, arguments, fn_sig.output, body) }); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index eb7cc7559e6a..54ac04bea9c4 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -19,7 +19,6 @@ use rustc::hir; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::FnKind; use rustc::hir::map::blocks::FnLikeNode; -use rustc::infer::InferCtxt; use rustc::traits::{self, ProjectionMode}; use rustc::ty::{self, TyCtxt, Ty}; use rustc::ty::cast::CastTy; @@ -1019,7 +1018,7 @@ impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants { // Statics must be Sync. if mode == Mode::Static { let ty = mir.return_ty.unwrap(); - InferCtxt::enter(tcx, None, None, ProjectionMode::AnyFinal, |infcx| { + tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| { let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); let mut fulfillment_cx = traits::FulfillmentContext::new(); fulfillment_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause); diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 9ad06e85c4fb..40157aa934c6 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -61,7 +61,7 @@ struct TypeVerifier<'a, 'b: 'a, 'gcx: 'b+'tcx, 'tcx: 'b> { errors_reported: bool } -impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx, 'tcx> { +impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { fn visit_span(&mut self, span: &Span) { if *span != DUMMY_SP { self.last_span = *span; @@ -104,8 +104,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx, 'tcx> { } } -impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx, 'tcx> { - fn new(cx: &'a mut TypeChecker<'b, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { +impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { + fn new(cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { TypeVerifier { cx: cx, mir: mir, @@ -114,11 +114,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx, 'tcx> { } } - fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { + fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.cx.infcx.tcx } - fn infcx(&self) -> &'a InferCtxt<'a, 'tcx, 'tcx> { + fn infcx(&self) -> &'a InferCtxt<'a, 'gcx, 'tcx> { self.cx.infcx } @@ -324,8 +324,8 @@ pub struct TypeChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { last_span: Span } -impl<'a, 'tcx> TypeChecker<'a, 'tcx, 'tcx> { - fn new(infcx: &'a InferCtxt<'a, 'tcx, 'tcx>) -> Self { +impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { + fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self { TypeChecker { infcx: infcx, fulfillment_cx: traits::FulfillmentContext::new(), @@ -349,7 +349,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx, 'tcx> { .map(|InferOk { obligations, .. }| assert!(obligations.is_empty())) } - fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { + fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.infcx.tcx } @@ -584,7 +584,7 @@ impl<'tcx> MirPass<'tcx> for TypeckMir { return; } let param_env = ty::ParameterEnvironment::for_item(tcx, src.item_id()); - InferCtxt::enter(tcx, None, Some(param_env), ProjectionMode::AnyFinal, |infcx| { + tcx.infer_ctxt(None, Some(param_env), ProjectionMode::AnyFinal).enter(|infcx| { let mut checker = TypeChecker::new(&infcx); { let mut verifier = TypeVerifier::new(&mut checker, mir); diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 80a4e421e34d..b1bb48aacee9 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -36,7 +36,6 @@ use rustc_const_math::{ConstMathErr, Op}; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::middle::expr_use_visitor as euv; -use rustc::infer::InferCtxt; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; use rustc::ty::{self, Ty, TyCtxt}; @@ -74,9 +73,9 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> { rvalue_borrows: NodeMap } -impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { +impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { fn with_mode(&mut self, mode: Mode, f: F) -> R where - F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>) -> R, + F: FnOnce(&mut CheckCrateVisitor<'a, 'gcx>) -> R, { let (old_mode, old_qualif) = (self.mode, self.qualif); self.mode = mode; @@ -88,14 +87,14 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { } fn with_euv(&mut self, item_id: Option, f: F) -> R where - F: for<'b> FnOnce(&mut euv::ExprUseVisitor<'b, 'tcx, 'tcx>) -> R, + F: for<'b, 'tcx> FnOnce(&mut euv::ExprUseVisitor<'b, 'gcx, 'tcx>) -> R, { let param_env = match item_id { Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id), None => self.tcx.empty_parameter_environment() }; - InferCtxt::enter(self.tcx, None, Some(param_env), ProjectionMode::AnyFinal, |infcx| { + self.tcx.infer_ctxt(None, Some(param_env), ProjectionMode::AnyFinal).enter(|infcx| { f(&mut euv::ExprUseVisitor::new(self, &infcx)) }) } @@ -178,7 +177,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { fn handle_const_fn_call(&mut self, _expr: &hir::Expr, def_id: DefId, - ret_ty: Ty<'tcx>) + ret_ty: Ty<'gcx>) -> bool { if let Some(fn_like) = lookup_const_fn_by_id(self.tcx, def_id) { let qualif = self.fn_like(fn_like.kind(), @@ -672,7 +671,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.sess.abort_if_errors(); } -impl<'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> { +impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { fn consume(&mut self, _consume_id: ast::NodeId, _consume_span: Span, diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs index 441154b7bf08..137a50642fcf 100644 --- a/src/librustc_passes/rvalues.rs +++ b/src/librustc_passes/rvalues.rs @@ -13,7 +13,6 @@ use rustc::dep_graph::DepNode; use rustc::middle::expr_use_visitor as euv; -use rustc::infer::InferCtxt; use rustc::middle::mem_categorization as mc; use rustc::ty::{self, TyCtxt, ParameterEnvironment}; use rustc::traits::ProjectionMode; @@ -41,10 +40,10 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for RvalueContext<'a, 'tcx> { fn_id: ast::NodeId) { // FIXME (@jroesch) change this to be an inference context let param_env = ParameterEnvironment::for_item(self.tcx, fn_id); - InferCtxt::enter(self.tcx, None, Some(param_env.clone()), - ProjectionMode::AnyFinal, |infcx| { + self.tcx.infer_ctxt(None, Some(param_env.clone()), + ProjectionMode::AnyFinal).enter(|infcx| { let mut delegate = RvalueContextDelegate { - tcx: self.tcx, + tcx: infcx.tcx, param_env: ¶m_env }; let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx); @@ -54,22 +53,23 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for RvalueContext<'a, 'tcx> { } } -struct RvalueContextDelegate<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: &'a ty::ParameterEnvironment<'tcx>, +struct RvalueContextDelegate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + param_env: &'a ty::ParameterEnvironment<'gcx>, } -impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> { +impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'gcx, 'tcx> { fn consume(&mut self, _: ast::NodeId, span: Span, cmt: mc::cmt<'tcx>, _: euv::ConsumeMode) { debug!("consume; cmt: {:?}; type: {:?}", *cmt, cmt.ty); - if !cmt.ty.is_sized(self.tcx, self.param_env, span) { + let ty = self.tcx.lift_to_global(&cmt.ty).unwrap(); + if !ty.is_sized(self.tcx.global_tcx(), self.param_env, span) { span_err!(self.tcx.sess, span, E0161, "cannot move a value of type {0}: the size of {0} cannot be statically determined", - cmt.ty); + ty); } } diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs index 4b656544bc44..6df308d5e624 100644 --- a/src/librustc_trans/_match.rs +++ b/src/librustc_trans/_match.rs @@ -194,7 +194,6 @@ use rustc_const_eval::{compare_lit_exprs, eval_const_expr}; use rustc::hir::def::{Def, DefMap}; use rustc::hir::def_id::DefId; use middle::expr_use_visitor as euv; -use rustc::infer::InferCtxt; use middle::lang_items::StrEqFnLangItem; use middle::mem_categorization as mc; use middle::mem_categorization::Categorization; @@ -1466,7 +1465,7 @@ fn is_discr_reassigned(bcx: Block, discr: &hir::Expr, body: &hir::Expr) -> bool field: field, reassigned: false }; - InferCtxt::enter_normalizing(bcx.tcx(), ProjectionMode::Any, |infcx| { + bcx.tcx().normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| { let mut visitor = euv::ExprUseVisitor::new(&mut rc, &infcx); visitor.walk_expr(body); }); diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 04f5e71497cf..1c393f8091ee 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -153,7 +153,7 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let symbol = symbol_names::exported_name(ccx, &instance); // Compute the rust-call form of the closure call method. - let sig = &ty::Tables::closure_type(&tcx.tables, tcx, closure_id, substs).sig; + let sig = &tcx.closure_type(closure_id, substs).sig; let sig = tcx.erase_late_bound_regions(sig); let sig = tcx.normalize_associated_type(&sig); let closure_type = tcx.mk_closure_from_closure_substs(closure_id, substs); @@ -217,9 +217,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, // this function (`trans_closure`) is invoked at the point // of the closure expression. - let sig = &ty::Tables::closure_type(&tcx.tables, tcx, - closure_def_id, - closure_substs).sig; + let sig = &tcx.closure_type(closure_def_id, closure_substs).sig; let sig = tcx.erase_late_bound_regions(sig); let sig = tcx.normalize_associated_type(&sig); @@ -349,7 +347,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( // Make a version with the type of by-ref closure. let ty::ClosureTy { unsafety, abi, mut sig } = - ty::Tables::closure_type(&tcx.tables, tcx, closure_def_id, substs); + tcx.closure_type(closure_def_id, substs); sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet let llref_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety, diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 05ed5abce145..dfab2bdbf644 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -530,7 +530,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { let exchange_malloc_fn_trans_item = create_fn_trans_item(self.scx.tcx(), exchange_malloc_fn_def_id, - self.ccx.tcx().mk_substs(Substs::empty()), + self.scx.tcx().mk_substs(Substs::empty()), self.param_substs); self.output.push(exchange_malloc_fn_trans_item); @@ -670,8 +670,8 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, let exchange_free_fn_trans_item = create_fn_trans_item(scx.tcx(), exchange_free_fn_def_id, - ccx.tcx().mk_substs(Substs::empty()), - ccx.tcx().mk_substs(Substs::empty())); + scx.tcx().mk_substs(Substs::empty()), + scx.tcx().mk_substs(Substs::empty())); output.push(exchange_free_fn_trans_item); } @@ -709,7 +709,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, let trans_item = create_fn_trans_item(scx.tcx(), destructor_did, substs, - ccx.tcx().mk_substs(Substs::empty())); + scx.tcx().mk_substs(Substs::empty())); output.push(trans_item); } @@ -1014,7 +1014,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, Some(create_fn_trans_item(scx.tcx(), impl_method.method.def_id, impl_method.substs, - ccx.tcx().mk_substs(Substs::empty()))) + scx.tcx().mk_substs(Substs::empty()))) } else { None } diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index f46ab8257361..c1685e6a7490 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -19,7 +19,7 @@ use llvm::{True, False, Bool, OperandBundleDef}; use rustc::cfg; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; -use rustc::infer::InferCtxt; +use rustc::infer::TransNormalize; use rustc::util::common::MemoizationMap; use middle::lang_items::LangItem; use rustc::ty::subst::Substs; @@ -428,7 +428,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { } pub fn monomorphize(&self, value: &T) -> T - where T : TypeFoldable<'tcx> + where T: TransNormalize<'tcx> { monomorphize::apply_param_substs(self.ccx.tcx(), self.param_substs, @@ -603,7 +603,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { } pub fn monomorphize(&self, value: &T) -> T - where T : TypeFoldable<'tcx> + where T: TransNormalize<'tcx> { monomorphize::apply_param_substs(self.tcx(), self.fcx.param_substs, @@ -710,7 +710,7 @@ impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> { } pub fn monomorphize(&self, value: &T) -> T - where T: TypeFoldable<'tcx> + where T: TransNormalize<'tcx> { self.bcx.monomorphize(value) } @@ -1066,7 +1066,7 @@ pub fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - let vtable = InferCtxt::enter_normalizing(tcx, ProjectionMode::Any, |infcx| { + tcx.normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); let obligation_cause = traits::ObligationCause::misc(span, @@ -1108,7 +1108,7 @@ pub fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, info!("Cache miss: {:?} => {:?}", trait_ref, vtable); vtable }) - }); + }) } /// Normalizes the predicates and checks whether they hold. If this @@ -1122,7 +1122,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("normalize_and_test_predicates(predicates={:?})", predicates); - InferCtxt::enter_normalizing(tcx, ProjectionMode::Any, |infcx| { + tcx.normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); let mut fulfill_cx = traits::FulfillmentContext::new(); let cause = traits::ObligationCause::dummy(); diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 4574c590a627..a29ff95851d7 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -18,7 +18,6 @@ use back::symbol_names; use llvm; use llvm::{ValueRef, get_param}; use middle::lang_items::ExchangeFreeFnLangItem; -use rustc::infer::InferCtxt; use rustc::ty::subst::{Substs}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; @@ -117,16 +116,15 @@ pub fn get_drop_glue_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match t.sty { ty::TyBox(typ) if !type_needs_drop(tcx, typ) && type_is_sized(tcx, typ) => { - let infcx = InferCtxt::normalizing(tcx, - &tcx.tables, - traits::ProjectionMode::Any); - let layout = t.layout(&infcx).unwrap(); - if layout.size(&tcx.data_layout).bytes() == 0 { - // `Box` does not allocate. - tcx.types.i8 - } else { - tcx.erase_regions(&t) - } + tcx.normalizing_infer_ctxt(traits::ProjectionMode::Any).enter(|infcx| { + let layout = t.layout(&infcx).unwrap(); + if layout.size(&tcx.data_layout).bytes() == 0 { + // `Box` does not allocate. + tcx.types.i8 + } else { + tcx.erase_regions(&t) + } + }) } _ => tcx.erase_regions(&t) } diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 1c559749a870..9b279a397f86 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -14,7 +14,6 @@ use arena::TypedArena; use back::symbol_names; use llvm::{ValueRef, get_params}; use rustc::hir::def_id::DefId; -use rustc::infer::InferCtxt; use rustc::ty::subst::{FnSpace, Subst, Substs}; use rustc::ty::subst; use rustc::traits::{self, ProjectionMode}; @@ -317,8 +316,14 @@ pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match trait_def.ancestors(impl_def_id).fn_defs(tcx, name).next() { Some(node_item) => { - let substs = InferCtxt::enter_normalizing(tcx, ProjectionMode::Any, |infcx| { - traits::translate_substs(&infcx, impl_def_id, substs, node_item.node) + let substs = tcx.normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| { + let substs = traits::translate_substs(&infcx, impl_def_id, + substs, node_item.node); + tcx.lift(&substs).unwrap_or_else(|| { + bug!("trans::meth::get_impl_method: translate_substs \ + returned {:?} which contains inference types/regions", + substs); + }) }); ImplMethod { method: node_item.item, diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index c1be6daefd3b..039304ece60b 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -13,6 +13,7 @@ use rustc::middle::const_val::ConstVal; use rustc_const_eval::ErrKind; use rustc_const_math::ConstInt::*; use rustc::hir::def_id::DefId; +use rustc::infer::TransNormalize; use rustc::mir::repr as mir; use rustc::mir::tcx::LvalueTy; use rustc::traits; @@ -252,7 +253,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } fn monomorphize(&self, value: &T) -> T - where T : TypeFoldable<'tcx> + where T: TransNormalize<'tcx> { monomorphize::apply_param_substs(self.ccx.tcx(), self.substs, diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 7c3feba5de74..8b1809e40233 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -12,6 +12,7 @@ use back::symbol_names; use llvm::ValueRef; use llvm; use rustc::hir::def_id::DefId; +use rustc::infer::TransNormalize; use rustc::ty::subst; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Ty, TypeFoldable, TyCtxt}; @@ -193,7 +194,7 @@ pub fn apply_param_substs<'a, 'tcx, T>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_substs: &Substs<'tcx>, value: &T) -> T - where T : TypeFoldable<'tcx> + where T: TransNormalize<'tcx> { let substituted = value.subst(tcx, param_substs); tcx.normalize_associated_type(&substituted) diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 9db7503b3abd..98ec87ebbcf6 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -11,7 +11,6 @@ #![allow(non_camel_case_types)] use rustc::hir::def_id::DefId; -use rustc::infer::InferCtxt; use rustc::ty::subst; use abi::FnType; use adt; @@ -124,7 +123,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ cx.llsizingtypes().borrow_mut().insert(t, llsizingty); // FIXME(eddyb) Temporary sanity check for ty::layout. - let layout = InferCtxt::enter_normalizing(cx.tcx(), ProjectionMode::Any, |infcx| { + let layout = cx.tcx().normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| { t.layout(&infcx) }); match layout { diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index fc02506b1cd8..a1a6a83d34ff 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -9,7 +9,7 @@ // except according to those terms. use middle::free_region::FreeRegionMap; -use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin}; +use rustc::infer::{self, InferOk, TypeOrigin}; use rustc::ty; use rustc::traits::{self, ProjectionMode}; use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace}; @@ -196,27 +196,22 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, return; } - // Create obligations for each predicate declared by the impl - // definition in the context of the trait's parameter - // environment. We can't just use `impl_env.caller_bounds`, - // however, because we want to replace all late-bound regions with - // region variables. - let impl_bounds = - impl_m.predicates.instantiate(tcx, impl_to_skol_substs); - - InferCtxt::enter(tcx, None, None, ProjectionMode::AnyFinal, |mut infcx| { + tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|mut infcx| { let mut fulfillment_cx = traits::FulfillmentContext::new(); - let (impl_bounds, _) = - infcx.replace_late_bound_regions_with_fresh_var( - impl_m_span, - infer::HigherRankedType, - &ty::Binder(impl_bounds)); - debug!("compare_impl_method: impl_bounds={:?}", - impl_bounds); // Normalize the associated types in the trait_bounds. let trait_bounds = trait_m.predicates.instantiate(tcx, &trait_to_skol_substs); + // Create obligations for each predicate declared by the impl + // definition in the context of the trait's parameter + // environment. We can't just use `impl_env.caller_bounds`, + // however, because we want to replace all late-bound regions with + // region variables. + let impl_bounds = + impl_m.predicates.instantiate(tcx, impl_to_skol_substs); + + debug!("compare_impl_method: impl_bounds={:?}", impl_bounds); + // Obtain the predicate split predicate sets for each. let trait_pred = trait_bounds.predicates.split(); let impl_pred = impl_bounds.predicates.split(); @@ -250,7 +245,12 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let mut selcx = traits::SelectionContext::new(&infcx); - for predicate in impl_pred.fns { + let (impl_pred_fns, _) = + infcx.replace_late_bound_regions_with_fresh_var( + impl_m_span, + infer::HigherRankedType, + &ty::Binder(impl_pred.fns)); + for predicate in impl_pred_fns { let traits::Normalized { value: predicate, .. } = traits::normalize(&mut selcx, normalize_cause.clone(), &predicate); @@ -285,6 +285,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs); let err = infcx.commit_if_ok(|snapshot| { + let tcx = infcx.tcx; let origin = TypeOrigin::MethodCompatCheck(impl_m_span); let (impl_sig, _) = @@ -421,7 +422,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, impl_trait_ref); let tcx = ccx.tcx; - InferCtxt::enter(tcx, None, None, ProjectionMode::AnyFinal, |infcx| { + tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| { let mut fulfillment_cx = traits::FulfillmentContext::new(); // The below is for the most part highly similar to the procedure diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 862dae4bb33e..ae614d7b0215 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -13,7 +13,7 @@ use check::regionck::RegionCtxt; use hir::def_id::DefId; use middle::free_region::FreeRegionMap; -use rustc::infer::{self, InferCtxt}; +use rustc::infer; use middle::region; use rustc::ty::subst::{self, Subst}; use rustc::ty::{self, Ty, TyCtxt}; @@ -84,7 +84,8 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( // check that the impl type can be made to match the trait type. let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id); - InferCtxt::enter(tcx, None, Some(impl_param_env), ProjectionMode::AnyFinal, |infcx| { + tcx.infer_ctxt(None, Some(impl_param_env), ProjectionMode::AnyFinal).enter(|infcx| { + let tcx = infcx.tcx; let mut fulfillment_cx = traits::FulfillmentContext::new(); let named_type = tcx.lookup_item_type(self_type_did).ty; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9e771d95bbd0..ad0ccdcf3890 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -372,17 +372,32 @@ impl<'a, 'gcx, 'tcx> Deref for FnCtxt<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { - fn enter(ccx: &'a CrateCtxt<'a, 'tcx>, - param_env: ty::ParameterEnvironment<'tcx>, - f: F) -> R - where F: for<'b> FnOnce(Inherited<'b, 'tcx, 'tcx>) -> R +/// Helper type of a temporary returned by ccx.inherited(...). +/// Necessary because we can't write the following bound: +/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Inherited<'b, 'gcx, 'tcx>). +pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + ccx: &'a CrateCtxt<'a, 'gcx>, + infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx> +} + +impl<'a, 'gcx, 'tcx> CrateCtxt<'a, 'gcx> { + pub fn inherited(&'a self, param_env: Option>) + -> InheritedBuilder<'a, 'gcx, 'tcx> { + InheritedBuilder { + ccx: self, + infcx: self.tcx.infer_ctxt(Some(ty::Tables::empty()), + param_env, + ProjectionMode::AnyFinal) + } + } +} + +impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> { + fn enter(&'tcx mut self, f: F) -> R + where F: for<'b> FnOnce(Inherited<'b, 'gcx, 'tcx>) -> R { - InferCtxt::enter(ccx.tcx, - Some(ty::Tables::empty()), - Some(param_env), - ProjectionMode::AnyFinal, - |infcx| { + let ccx = self.ccx; + self.infcx.enter(|infcx| { f(Inherited { ccx: ccx, infcx: infcx, @@ -393,7 +408,9 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { }) }) } +} +impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { fn normalize_associated_types_in(&self, span: Span, body_id: ast::NodeId, @@ -491,7 +508,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, _ => span_bug!(body.span, "check_bare_fn: function type expected") }; - Inherited::enter(ccx, param_env, |inh| { + ccx.inherited(Some(param_env)).enter(|inh| { // Compute the fty from point of view of inside fn. let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body.id); let fn_sig = @@ -1124,7 +1141,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>, expr: &'tcx hir::Expr, expected_type: Ty<'tcx>) { - Inherited::enter(ccx, ccx.tcx.empty_parameter_environment(), |inh| { + ccx.inherited(None).enter(|inh| { let fcx = FnCtxt::new(&inh, ty::FnConverging(expected_type), expr.id); fcx.check_const_with_ty(expr.span, expr, expected_type); }); @@ -1134,7 +1151,7 @@ fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, sp: Span, e: &'tcx hir::Expr, id: ast::NodeId) { - Inherited::enter(ccx, ccx.tcx.empty_parameter_environment(), |inh| { + ccx.inherited(None).enter(|inh| { let rty = ccx.tcx.node_id_to_type(id); let fcx = FnCtxt::new(&inh, ty::FnConverging(rty), e.id); let declty = fcx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(id)).ty; @@ -1208,7 +1225,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, "unsupported representation for zero-variant enum"); } - Inherited::enter(ccx, ccx.tcx.empty_parameter_environment(), |inh| { + ccx.inherited(None).enter(|inh| { let rty = ccx.tcx.node_id_to_type(id); let fcx = FnCtxt::new(&inh, ty::FnConverging(rty), id); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 7739bb6bb8fd..bb63cf11d9ad 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use check::{FnCtxt, Inherited}; +use check::FnCtxt; use constrained_type_params::{identify_constrained_type_params, Parameter}; use CrateCtxt; use hir::def_id::DefId; @@ -30,16 +30,46 @@ pub struct CheckTypeWellFormedVisitor<'ccx, 'tcx:'ccx> { code: traits::ObligationCauseCode<'tcx>, } -impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { - pub fn new(ccx: &'ccx CrateCtxt<'ccx, 'tcx>) - -> CheckTypeWellFormedVisitor<'ccx, 'tcx> { +/// Helper type of a temporary returned by .for_item(...). +/// Necessary because we can't write the following bound: +/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>). +struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>, + code: traits::ObligationCauseCode<'gcx>, + id: ast::NodeId, + span: Span +} + +impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { + fn with_fcx(&'tcx mut self, f: F) where + F: for<'b> FnOnce(&FnCtxt<'b, 'gcx, 'tcx>, + &mut CheckTypeWellFormedVisitor<'b, 'gcx>) -> Vec> + { + let code = self.code.clone(); + let id = self.id; + let span = self.span; + self.inherited.enter(|inh| { + let fcx = FnCtxt::new(&inh, ty::FnDiverging, id); + let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor { + ccx: fcx.ccx, + code: code + }); + fcx.select_all_obligations_or_error(); + fcx.regionck_item(id, span, &wf_tys); + }); + } +} + +impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { + pub fn new(ccx: &'ccx CrateCtxt<'ccx, 'gcx>) + -> CheckTypeWellFormedVisitor<'ccx, 'gcx> { CheckTypeWellFormedVisitor { ccx: ccx, code: traits::ObligationCauseCode::MiscObligation } } - fn tcx(&self) -> TyCtxt<'ccx, 'tcx, 'tcx> { + fn tcx(&self) -> TyCtxt<'ccx, 'gcx, 'gcx> { self.ccx.tcx } @@ -128,7 +158,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { fn check_trait_or_impl_item(&mut self, item_id: ast::NodeId, span: Span) { let code = self.code.clone(); - self.with_fcx(item_id, span, |fcx, this| { + self.for_id(item_id, span).with_fcx(|fcx, this| { let free_substs = &fcx.parameter_environment.free_substs; let free_id_outlive = fcx.parameter_environment.free_id_outlive; @@ -166,32 +196,28 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { }) } - fn with_item_fcx(&mut self, item: &hir::Item, f: F) where - F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx, 'tcx>, - &mut CheckTypeWellFormedVisitor<'ccx,'tcx>) -> Vec>, - { - self.with_fcx(item.id, item.span, f) + fn for_item<'tcx>(&self, item: &hir::Item) + -> CheckWfFcxBuilder<'ccx, 'gcx, 'tcx> { + self.for_id(item.id, item.span) } - fn with_fcx(&mut self, id: ast::NodeId, span: Span, mut f: F) where - F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx, 'tcx>, - &mut CheckTypeWellFormedVisitor<'ccx,'tcx>) -> Vec>, - { - let ccx = self.ccx; - let param_env = ty::ParameterEnvironment::for_item(ccx.tcx, id); - Inherited::enter(ccx, param_env, |inh| { - let fcx = FnCtxt::new(&inh, ty::FnDiverging, id); - let wf_tys = f(&fcx, self); - fcx.select_all_obligations_or_error(); - fcx.regionck_item(id, span, &wf_tys); - }); + fn for_id<'tcx>(&self, id: ast::NodeId, span: Span) + -> CheckWfFcxBuilder<'ccx, 'gcx, 'tcx> { + let param_env = ty::ParameterEnvironment::for_item(self.ccx.tcx, id); + CheckWfFcxBuilder { + inherited: self.ccx.inherited(Some(param_env)), + code: self.code.clone(), + id: id, + span: span + } } /// In a type definition, we check that to ensure that the types of the fields are well-formed. fn check_type_defn(&mut self, item: &hir::Item, mut lookup_fields: F) where - F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx, 'tcx>) -> Vec>, + F: for<'fcx, 'tcx> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx>) + -> Vec> { - self.with_item_fcx(item, |fcx, this| { + self.for_item(item).with_fcx(|fcx, this| { let variants = lookup_fields(fcx); for variant in &variants { @@ -234,7 +260,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { } } - self.with_item_fcx(item, |fcx, this| { + self.for_item(item).with_fcx(|fcx, this| { let free_substs = &fcx.parameter_environment.free_substs; let predicates = fcx.tcx.lookup_predicates(trait_def_id); let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates); @@ -247,7 +273,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { item: &hir::Item, body: &hir::Block) { - self.with_item_fcx(item, |fcx, this| { + self.for_item(item).with_fcx(|fcx, this| { let free_substs = &fcx.parameter_environment.free_substs; let type_scheme = fcx.tcx.lookup_item_type(fcx.tcx.map.local_def_id(item.id)); let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &type_scheme.ty); @@ -274,7 +300,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { { debug!("check_item_type: {:?}", item); - self.with_item_fcx(item, |fcx, this| { + self.for_item(item).with_fcx(|fcx, this| { let type_scheme = fcx.tcx.lookup_item_type(fcx.tcx.map.local_def_id(item.id)); let item_ty = fcx.instantiate_type_scheme(item.span, &fcx.parameter_environment @@ -294,7 +320,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { { debug!("check_impl: {:?}", item); - self.with_item_fcx(item, |fcx, this| { + self.for_item(item).with_fcx(|fcx, this| { let free_substs = &fcx.parameter_environment.free_substs; let item_def_id = fcx.tcx.map.local_def_id(item.id); @@ -328,10 +354,10 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { }); } - fn check_where_clauses<'fcx>(&mut self, - fcx: &FnCtxt<'fcx,'tcx, 'tcx>, - span: Span, - predicates: &ty::InstantiatedPredicates<'tcx>) + fn check_where_clauses<'fcx, 'tcx>(&mut self, + fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, + span: Span, + predicates: &ty::InstantiatedPredicates<'tcx>) { let obligations = predicates.predicates @@ -346,13 +372,13 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { } } - fn check_fn_or_method<'fcx>(&mut self, - fcx: &FnCtxt<'fcx,'tcx, 'tcx>, - span: Span, - fty: &'tcx ty::BareFnTy<'tcx>, - predicates: &ty::InstantiatedPredicates<'tcx>, - free_id_outlive: CodeExtent, - implied_bounds: &mut Vec>) + fn check_fn_or_method<'fcx, 'tcx>(&mut self, + fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, + span: Span, + fty: &'tcx ty::BareFnTy<'tcx>, + predicates: &ty::InstantiatedPredicates<'tcx>, + free_id_outlive: CodeExtent, + implied_bounds: &mut Vec>) { let free_substs = &fcx.parameter_environment.free_substs; let fty = fcx.instantiate_type_scheme(span, free_substs, &fty); @@ -376,12 +402,12 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { self.check_where_clauses(fcx, span, predicates); } - fn check_method_receiver<'fcx>(&mut self, - fcx: &FnCtxt<'fcx,'tcx, 'tcx>, - span: Span, - method: &ty::Method<'tcx>, - free_id_outlive: CodeExtent, - self_ty: ty::Ty<'tcx>) + fn check_method_receiver<'fcx, 'tcx>(&mut self, + fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, + span: Span, + method: &ty::Method<'tcx>, + free_id_outlive: CodeExtent, + self_ty: ty::Ty<'tcx>) { // check that the type of the method's receiver matches the // method's first parameter. @@ -549,7 +575,7 @@ struct AdtField<'tcx> { span: Span, } -impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> { +impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn struct_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> { let fields = struct_def.fields().iter() diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 8c0e11780b21..33238f6cda77 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -56,7 +56,7 @@ struct CoherenceCheckVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { cc: &'a CoherenceChecker<'a, 'gcx, 'tcx> } -impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx, 'tcx> { +impl<'a, 'gcx, 'tcx, 'v> intravisit::Visitor<'v> for CoherenceCheckVisitor<'a, 'gcx, 'tcx> { fn visit_item(&mut self, item: &Item) { if let ItemImpl(..) = item.node { self.cc.check_implementation(item) @@ -64,7 +64,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx, ' } } -impl<'a, 'tcx> CoherenceChecker<'a, 'tcx, 'tcx> { +impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { // Returns the def ID of the base type, if there is one. fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option { @@ -187,7 +187,7 @@ fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option { Rc::new(RefCell::new(vec!(impl_def_id)))); } - fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) { + fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'gcx>, impl_def_id: DefId) { debug!("add_trait_impl: impl_trait_ref={:?} impl_def_id={:?}", impl_trait_ref, impl_def_id); let trait_def = self.crate_context.tcx.lookup_trait_def(impl_trait_ref.def_id); @@ -376,10 +376,10 @@ fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option { debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)", source, target); - InferCtxt::enter(tcx, None, Some(param_env), ProjectionMode::Topmost, |infcx| { + tcx.infer_ctxt(None, Some(param_env), ProjectionMode::Topmost).enter(|infcx| { let origin = TypeOrigin::Misc(span); - let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>, - mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| { + let check_mutbl = |mt_a: ty::TypeAndMut<'gcx>, mt_b: ty::TypeAndMut<'gcx>, + mk_ptr: &Fn(Ty<'gcx>) -> Ty<'gcx>| { if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) { infcx.report_mismatched_types(origin, mk_ptr(mt_b.ty), target, ty::error::TypeError::Mutability); @@ -513,7 +513,7 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def pub fn check_coherence(ccx: &CrateCtxt) { let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence); - InferCtxt::enter(ccx.tcx, None, None, ProjectionMode::Topmost, |infcx| { + ccx.tcx.infer_ctxt(None, None, ProjectionMode::Topmost).enter(|infcx| { CoherenceChecker { crate_context: ccx, inference_context: infcx, diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 0f0a5b5241e7..dcaa5cfb20a4 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -14,7 +14,6 @@ use hir::def_id::DefId; use rustc::traits::{self, ProjectionMode}; -use rustc::infer::InferCtxt; use rustc::ty::{self, TyCtxt}; use syntax::ast; use rustc::dep_graph::DepNode; @@ -85,7 +84,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { for (i, &impl1_def_id) in impls.iter().enumerate() { for &impl2_def_id in &impls[(i+1)..] { - InferCtxt::enter(self.tcx, None, None, ProjectionMode::Topmost, |infcx| { + self.tcx.infer_ctxt(None, None, ProjectionMode::Topmost).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 3c46d962198f..b88b3c9802d3 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -104,7 +104,7 @@ pub use rustc::util; use dep_graph::DepNode; use hir::map as hir_map; use hir::def::Def; -use rustc::infer::{InferCtxt, TypeOrigin}; +use rustc::infer::TypeOrigin; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::traits::ProjectionMode; @@ -211,7 +211,7 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, t2: Ty<'tcx>, msg: &str) -> bool { - InferCtxt::enter(ccx.tcx, None, None, ProjectionMode::AnyFinal, |infcx| { + ccx.tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| { if let Err(err) = infcx.eq_types(false, TypeOrigin::Misc(span), t1, t2) { emit_type_err(infcx.tcx, span, t1, t2, &err, msg); false