diff options
| author | Jared Roesch <roeschinc@gmail.com> | 2015-06-24 13:40:54 -0700 |
|---|---|---|
| committer | Jared Roesch <roeschinc@gmail.com> | 2015-06-27 13:43:20 -0700 |
| commit | 79d02895fffa865c6a4ccfaad1fa35d8f732d497 (patch) | |
| tree | 584bc9abdae9e1949cbdd72494630b5db4fd15ca /src | |
| parent | 2ba46f8bbc6fdf10e434faea52b9ca20e0d9f2eb (diff) | |
| download | rust-79d02895fffa865c6a4ccfaad1fa35d8f732d497.tar.gz rust-79d02895fffa865c6a4ccfaad1fa35d8f732d497.zip | |
Begin refactor type checking state
This first patch starts by moving around pieces of state related to type checking. The goal is to slowly unify the type checking state into a single typing context. This initial patch moves the ParameterEnvironment into the InferCtxt and moves shared tables from Inherited and ty::ctxt into their own struct Tables. This is the foundational work to refactoring the type checker to enable future evolution of the language and tooling.
Diffstat (limited to 'src')
45 files changed, 427 insertions, 252 deletions
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index c19ba19f5b7..2cec42b76bc 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -61,6 +61,7 @@ #![feature(str_match_indices)] #![feature(vec_push_all)] #![feature(wrapping)] +#![feature(cell_extras)] #![cfg_attr(test, feature(test))] #![allow(trivial_casts)] diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 21e2ad19881..f2ae396173b 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1027,7 +1027,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, }) } - if let Some(item_substs) = tcx.item_substs.borrow().get(&id) { + if let Some(item_substs) = tcx.tables.borrow().item_substs.get(&id) { rbml_w.tag(c::tag_table_item_subst, |rbml_w| { rbml_w.id(id); rbml_w.emit_substs(ecx, &item_substs.substs); @@ -1051,7 +1051,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, var_id: var_id, closure_expr_id: id }; - let upvar_capture = tcx.upvar_capture_map.borrow().get(&upvar_id).unwrap().clone(); + let upvar_capture = tcx.tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone(); var_id.encode(rbml_w); upvar_capture.encode(rbml_w); }) @@ -1074,19 +1074,19 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, } let method_call = MethodCall::expr(id); - if let Some(method) = tcx.method_map.borrow().get(&method_call) { + if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) { rbml_w.tag(c::tag_table_method_map, |rbml_w| { rbml_w.id(id); encode_method_callee(ecx, rbml_w, method_call.autoderef, method) }) } - if let Some(adjustment) = tcx.adjustments.borrow().get(&id) { + if let Some(adjustment) = tcx.tables.borrow().adjustments.get(&id) { match *adjustment { ty::AdjustDerefRef(ref adj) => { for autoderef in 0..adj.autoderefs { let method_call = MethodCall::autoderef(id, autoderef as u32); - if let Some(method) = tcx.method_map.borrow().get(&method_call) { + if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) { rbml_w.tag(c::tag_table_method_map, |rbml_w| { rbml_w.id(id); encode_method_callee(ecx, rbml_w, @@ -1104,14 +1104,14 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, }) } - if let Some(closure_type) = tcx.closure_tys.borrow().get(&ast_util::local_def(id)) { + if let Some(closure_type) = tcx.tables.borrow().closure_tys.get(&ast_util::local_def(id)) { rbml_w.tag(c::tag_table_closure_tys, |rbml_w| { rbml_w.id(id); rbml_w.emit_closure_type(ecx, closure_type); }) } - if let Some(closure_kind) = tcx.closure_kinds.borrow().get(&ast_util::local_def(id)) { + if let Some(closure_kind) = tcx.tables.borrow().closure_kinds.get(&ast_util::local_def(id)) { rbml_w.tag(c::tag_table_closure_kinds, |rbml_w| { rbml_w.id(id); encode_closure_kind(rbml_w, *closure_kind) @@ -1630,7 +1630,7 @@ fn decode_side_tables(dcx: &DecodeContext, let item_substs = ty::ItemSubsts { substs: val_dsr.read_substs(dcx) }; - dcx.tcx.item_substs.borrow_mut().insert( + dcx.tcx.tables.borrow_mut().item_substs.insert( id, item_substs); } c::tag_table_freevars => { @@ -1646,7 +1646,7 @@ fn decode_side_tables(dcx: &DecodeContext, closure_expr_id: id }; let ub: ty::UpvarCapture = Decodable::decode(val_dsr).unwrap(); - dcx.tcx.upvar_capture_map.borrow_mut().insert(upvar_id, ub.tr(dcx)); + dcx.tcx.tables.borrow_mut().upvar_capture_map.insert(upvar_id, ub.tr(dcx)); } c::tag_table_tcache => { let type_scheme = val_dsr.read_type_scheme(dcx); @@ -1663,22 +1663,22 @@ fn decode_side_tables(dcx: &DecodeContext, expr_id: id, autoderef: autoderef }; - dcx.tcx.method_map.borrow_mut().insert(method_call, method); + dcx.tcx.tables.borrow_mut().method_map.insert(method_call, method); } c::tag_table_adjustments => { let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(dcx); - dcx.tcx.adjustments.borrow_mut().insert(id, adj); + dcx.tcx.tables.borrow_mut().adjustments.insert(id, adj); } c::tag_table_closure_tys => { let closure_ty = val_dsr.read_closure_ty(dcx); - dcx.tcx.closure_tys.borrow_mut().insert(ast_util::local_def(id), + dcx.tcx.tables.borrow_mut().closure_tys.insert(ast_util::local_def(id), closure_ty); } c::tag_table_closure_kinds => { let closure_kind = val_dsr.read_closure_kind(dcx); - dcx.tcx.closure_kinds.borrow_mut().insert(ast_util::local_def(id), + dcx.tcx.tables.borrow_mut().closure_kinds.insert(ast_util::local_def(id), closure_kind); } c::tag_table_cast_kinds => { diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 801b3a721e4..7d62b6ff900 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -411,7 +411,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { func_or_rcvr: &ast::Expr, args: I) -> CFGIndex { let method_call = ty::MethodCall::expr(call_expr.id); - let fn_ty = match self.tcx.method_map.borrow().get(&method_call) { + let fn_ty = match self.tcx.tables.borrow().method_map.get(&method_call) { Some(method) => method.ty, None => self.tcx.expr_ty_adjusted(func_or_rcvr) }; @@ -634,6 +634,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn is_method_call(&self, expr: &ast::Expr) -> bool { let method_call = ty::MethodCall::expr(expr.id); - self.tcx.method_map.borrow().contains_key(&method_call) + self.tcx.tables.borrow().method_map.contains_key(&method_call) } } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 62bf1648725..b156a2c087b 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -283,12 +283,11 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { fn check_static_type(&self, e: &ast::Expr) { let ty = self.tcx.node_id_to_type(e.id); - let infcx = infer::new_infer_ctxt(self.tcx); + let infcx = infer::new_infer_ctxt(self.tcx, None); let mut fulfill_cx = traits::FulfillmentContext::new(false); let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic); fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause); - let env = self.tcx.empty_parameter_environment(); - match fulfill_cx.select_all_or_error(&infcx, &env) { + match fulfill_cx.select_all_or_error(&infcx, &infcx.parameter_environment) { Ok(()) => { }, Err(ref errors) => { traits::report_fulfillment_errors(&infcx, errors); @@ -544,7 +543,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, match e.node { ast::ExprUnary(..) | ast::ExprBinary(..) | - ast::ExprIndex(..) if v.tcx.method_map.borrow().contains_key(&method_call) => { + ast::ExprIndex(..) if v.tcx.tables.borrow().method_map.contains_key(&method_call) => { v.add_qualif(ConstQualif::NOT_CONST); if v.mode != Mode::Var { span_err!(v.tcx.sess, e.span, E0011, @@ -695,7 +694,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, } } ast::ExprMethodCall(..) => { - let method_did = match v.tcx.method_map.borrow()[&method_call].origin { + let method_did = match v.tcx.tables.borrow().method_map[&method_call].origin { ty::MethodStatic(did) => Some(did), _ => None }; diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index d2b3b83e4f4..f61884e2136 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -98,6 +98,7 @@ impl<'a> FromIterator<Vec<&'a Pat>> for Matrix<'a> { } } +//NOTE: appears to be the only place other then InferCtxt to contain a ParamEnv pub struct MatchCheckCtxt<'a, 'tcx: 'a> { pub tcx: &'a ty::ctxt<'tcx>, pub param_env: ParameterEnvironment<'a, 'tcx>, diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 1b1725dd15c..8f19a6e9e15 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -1031,10 +1031,9 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>, substs: trait_substs }); tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id()); - let infcx = infer::new_infer_ctxt(tcx); + let infcx = infer::new_infer_ctxt(tcx, None); - let param_env = tcx.empty_parameter_environment(); - let mut selcx = traits::SelectionContext::new(&infcx, ¶m_env); + let mut selcx = traits::SelectionContext::new(&infcx, &infcx.parameter_environment); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), trait_ref.to_poly_trait_predicate()); let selection = match selcx.select(&obligation) { diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index bd8b8afbdfe..d8ee38b8478 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -96,7 +96,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn lookup_and_handle_method(&mut self, id: ast::NodeId, span: codemap::Span) { let method_call = ty::MethodCall::expr(id); - match self.tcx.method_map.borrow().get(&method_call) { + match self.tcx.tables.borrow().method_map.get(&method_call) { Some(method) => { match method.origin { ty::MethodStatic(def_id) => { diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index c48d5d5da40..8084c2b0c39 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -140,7 +140,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { match expr.node { ast::ExprMethodCall(_, _, _) => { let method_call = MethodCall::expr(expr.id); - let base_type = self.tcx.method_map.borrow().get(&method_call).unwrap().ty; + let base_type = self.tcx.tables.borrow().method_map.get(&method_call).unwrap().ty; debug!("effect: method call case, base type is {:?}", base_type); if type_is_unsafe_function(base_type) { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index a15d02ea296..25728c50c61 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -257,8 +257,9 @@ impl OverloadedCallType { fn from_closure(tcx: &ty::ctxt, closure_did: ast::DefId) -> OverloadedCallType { let trait_did = - tcx.closure_kinds + tcx.tables .borrow() + .closure_kinds .get(&closure_did) .expect("OverloadedCallType::from_closure: didn't find closure id") .trait_did(tcx); @@ -787,8 +788,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // process. fn walk_adjustment(&mut self, expr: &ast::Expr) { let typer = self.typer; - if let Some(adjustment) = typer.adjustments().borrow().get(&expr.id) { - match *adjustment { + //NOTE(@jroesch): mixed RefCell borrow causes crash + let adj = typer.adjustments().get(&expr.id).map(|x| x.clone()); + if let Some(adjustment) = adj { + match adjustment { ty::AdjustReifyFnPointer | ty::AdjustUnsafeFnPointer => { // Creating a closure/fn-pointer or unsizing consumes diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index f1af2705d4e..8e53747e899 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -77,6 +77,10 @@ pub struct InferCtxt<'a, 'tcx: 'a> { // For region variables. region_vars: RegionVarBindings<'a, 'tcx>, + + pub parameter_environment: ty::ParameterEnvironment<'a, 'tcx>, + + // pub tables: &'a RefCell<ty::Tables<'tcx>> } /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized @@ -309,7 +313,8 @@ pub fn fixup_err_to_string(f: fixup_err) -> String { } } -pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>) +pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>, + param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>) -> InferCtxt<'a, 'tcx> { InferCtxt { tcx: tcx, @@ -317,6 +322,7 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>) 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()) } } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index d354c1667da..7d237a511c4 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1150,7 +1150,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { ast::ExprMethodCall(_, _, ref args) => { let method_call = ty::MethodCall::expr(expr.id); - let method_ty = self.ir.tcx.method_map.borrow().get(&method_call).unwrap().ty; + let method_ty = self.ir.tcx.tables.borrow().method_map.get(&method_call).unwrap().ty; let succ = if method_ty.fn_ret().diverges() { self.s.exit_ln } else { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 969ffaf88a7..13e127e9126 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -83,7 +83,7 @@ use syntax::ast::{MutImmutable, MutMutable}; use syntax::ast; use syntax::codemap::Span; -use std::cell::RefCell; +use std::cell::Ref; use std::fmt; use std::rc::Rc; @@ -289,7 +289,7 @@ pub trait Typer<'tcx> : ty::ClosureTyper<'tcx> { fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>>; fn node_method_origin(&self, method_call: ty::MethodCall) -> Option<ty::MethodOrigin<'tcx>>; - fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>; + fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>>; fn is_method_call(&self, id: ast::NodeId) -> bool; fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent>; fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture>; @@ -408,7 +408,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { let unadjusted_ty = try!(self.expr_ty(expr)); Ok(unadjusted_ty.adjust( self.tcx(), expr.span, expr.id, - self.typer.adjustments().borrow().get(&expr.id), + self.typer.adjustments().get(&expr.id), |method_call| self.typer.node_method_ty(method_call))) } @@ -440,7 +440,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } pub fn cat_expr(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> { - match self.typer.adjustments().borrow().get(&expr.id) { + match self.typer.adjustments().get(&expr.id) { None => { // No adjustments. self.cat_expr_unadjusted(expr) diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 0bbcfa70038..6ea726062ca 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -128,7 +128,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> { } ast::ExprMethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - match (*self.tcx.method_map.borrow()).get(&method_call).unwrap().origin { + match self.tcx.tables.borrow().method_map.get(&method_call).unwrap().origin { ty::MethodStatic(def_id) => { if is_local(def_id) { if self.def_id_represents_local_inlined_item(def_id) { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 4766ae8933d..e6bbae6405b 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -406,7 +406,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr, ast::ExprMethodCall(i, _, _) => { span = i.span; let method_call = ty::MethodCall::expr(e.id); - match tcx.method_map.borrow().get(&method_call) { + match tcx.tables.borrow().method_map.get(&method_call) { Some(method) => { match method.origin { ty::MethodStatic(def_id) => { diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 845ba62307f..eb839eade14 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -351,6 +351,7 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, } } +// TODO: this is gonna need to be removed ... /// Normalizes the parameter environment, reporting errors if they occur. pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvironment<'a,'tcx>, cause: ObligationCause<'tcx>) @@ -396,13 +397,13 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi let elaborated_env = unnormalized_env.with_caller_bounds(predicates); - let infcx = infer::new_infer_ctxt(tcx); - let predicates = match fully_normalize(&infcx, &elaborated_env, cause, - &elaborated_env.caller_bounds) { + let infcx = infer::new_infer_ctxt(tcx, Some(elaborated_env)); + let predicates = match fully_normalize(&infcx, &infcx.parameter_environment, cause, + &infcx.parameter_environment.caller_bounds) { Ok(predicates) => predicates, Err(errors) => { report_fulfillment_errors(&infcx, &errors); - return unnormalized_env; // an unnormalized env is better than nothing + return infcx.parameter_environment; // an unnormalized env is better than nothing } }; @@ -420,11 +421,11 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi // all things considered. let err_msg = fixup_err_to_string(fixup_err); tcx.sess.span_err(span, &err_msg); - return elaborated_env; // an unnormalized env is better than nothing + return infcx.parameter_environment; // an unnormalized env is better than nothing } }; - elaborated_env.with_caller_bounds(predicates) + infcx.parameter_environment.with_caller_bounds(predicates) } pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 302ec08db6f..cdf7f6ef9b6 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -728,7 +728,7 @@ impl MethodCall { // maps from an expression id that corresponds to a method call to the details // of the method to be invoked -pub type MethodMap<'tcx> = RefCell<FnvHashMap<MethodCall, MethodCallee<'tcx>>>; +pub type MethodMap<'tcx> = FnvHashMap<MethodCall, MethodCallee<'tcx>>; // Contains information needed to resolve types and (in the future) look up // the types of AST nodes. @@ -815,6 +815,48 @@ pub struct CommonTypes<'tcx> { pub err: Ty<'tcx>, } +pub struct Tables<'tcx> { + /// Stores the types for various nodes in the AST. Note that this table + /// is not guaranteed to be populated until after typeck. See + /// typeck::check::fn_ctxt for details. + pub node_types: NodeMap<Ty<'tcx>>, + + /// Stores the type parameters which were substituted to obtain the type + /// of this node. This only applies to nodes that refer to entities + /// parameterized by type parameters, such as generic fns, types, or + /// other items. + pub item_substs: NodeMap<ItemSubsts<'tcx>>, + + pub adjustments: NodeMap<ty::AutoAdjustment<'tcx>>, + + pub method_map: MethodMap<'tcx>, + + /// Borrows + pub upvar_capture_map: UpvarCaptureMap, + + /// Records the type of each closure. The def ID is the ID of the + /// expression defining the closure. + pub closure_tys: DefIdMap<ClosureTy<'tcx>>, + + /// Records the type of each closure. The def ID is the ID of the + /// expression defining the closure. + pub closure_kinds: DefIdMap<ClosureKind>, +} + +impl<'tcx> Tables<'tcx> { + pub fn empty() -> Tables<'tcx> { + Tables { + node_types: FnvHashMap(), + item_substs: NodeMap(), + adjustments: NodeMap(), + method_map: FnvHashMap(), + upvar_capture_map: FnvHashMap(), + closure_tys: DefIdMap(), + closure_kinds: DefIdMap(), + } + } +} + /// The data structure to keep track of all the information that typechecker /// generates so that so that it can be reused and doesn't have to be redone /// later on. @@ -850,17 +892,9 @@ pub struct ctxt<'tcx> { // borrowck. (They are not used during trans, and hence are not // serialized or needed for cross-crate fns.) free_region_maps: RefCell<NodeMap<FreeRegionMap>>, + // FIXME: jroesch make this a refcell - /// Stores the types for various nodes in the AST. Note that this table - /// is not guaranteed to be populated until after typeck. See - /// typeck::check::fn_ctxt for details. - node_types: RefCell<NodeMap<Ty<'tcx>>>, - - /// Stores the type parameters which were substituted to obtain the type - /// of this node. This only applies to nodes that refer to entities - /// parameterized by type parameters, such as generic fns, types, or - /// other items. - pub item_substs: RefCell<NodeMap<ItemSubsts<'tcx>>>, + pub tables: RefCell<Tables<'tcx>>, /// Maps from a trait item to the trait item "descriptor" pub impl_or_trait_items: RefCell<DefIdMap<ImplOrTraitItem<'tcx>>>, @@ -894,7 +928,6 @@ pub struct ctxt<'tcx> { pub ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>, pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo<'tcx>>>>>>, pub ty_param_defs: RefCell<NodeMap<TypeParameterDef<'tcx>>>, - pub adjustments: RefCell<NodeMap<AutoAdjustment<'tcx>>>, pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>, pub lang_items: middle::lang_items::LanguageItems, /// A mapping of fake provided method def_ids to the default implementation @@ -944,26 +977,13 @@ pub struct ctxt<'tcx> { /// FIXME(arielb1): why is this separate from populated_external_types? pub populated_external_primitive_impls: RefCell<DefIdSet>, - /// Borrows - pub upvar_capture_map: RefCell<UpvarCaptureMap>, - /// These caches are used by const_eval when decoding external constants. pub extern_const_statics: RefCell<DefIdMap<ast::NodeId>>, pub extern_const_variants: RefCell<DefIdMap<ast::NodeId>>, pub extern_const_fns: RefCell<DefIdMap<ast::NodeId>>, - pub method_map: MethodMap<'tcx>, - pub dependency_formats: RefCell<dependency_format::Dependencies>, - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - pub closure_kinds: RefCell<DefIdMap<ClosureKind>>, - - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - pub closure_tys: RefCell<DefIdMap<ClosureTy<'tcx>>>, - pub node_lint_levels: RefCell<FnvHashMap<(ast::NodeId, lint::LintId), lint::LevelSource>>, @@ -1000,9 +1020,16 @@ pub struct ctxt<'tcx> { } impl<'tcx> ctxt<'tcx> { - pub fn node_types(&self) -> Ref<NodeMap<Ty<'tcx>>> { self.node_types.borrow() } + pub fn node_types(&self) -> Ref<NodeMap<Ty<'tcx>>> { + fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap<Ty<'tcx>> { + &tables.node_types + } + + Ref::map(self.tables.borrow(), projection) + } + pub fn node_type_insert(&self, id: NodeId, ty: Ty<'tcx>) { - self.node_types.borrow_mut().insert(id, ty); + self.tables.borrow_mut().node_types.insert(id, ty); } pub fn intern_trait_def(&self, def: TraitDef<'tcx>) -> &'tcx TraitDef<'tcx> { @@ -3195,6 +3222,84 @@ impl<'tcx> CommonTypes<'tcx> { } } +/// Create a type context and call the closure with a `&ty::ctxt` reference +/// to the context. The closure enforces that the type context and any interned +/// value (types, substs, etc.) can only be used while `ty::tls` has a valid +/// reference to the context, to allow formatting values that need it. +pub fn with_ctxt<'tcx, F, R>(s: Session, + arenas: &'tcx CtxtArenas<'tcx>, + def_map: DefMap, + named_region_map: resolve_lifetime::NamedRegionMap, + map: ast_map::Map<'tcx>, + freevars: RefCell<FreevarMap>, + region_maps: RegionMaps, + lang_items: middle::lang_items::LanguageItems, + stability: stability::Index<'tcx>, + f: F) -> (Session, R) + where F: FnOnce(&ctxt<'tcx>) -> R +{ + let mut interner = FnvHashMap(); + let common_types = CommonTypes::new(&arenas.type_, &mut interner); + + tls::enter(ctxt { + arenas: arenas, + interner: RefCell::new(interner), + substs_interner: RefCell::new(FnvHashMap()), + bare_fn_interner: RefCell::new(FnvHashMap()), + region_interner: RefCell::new(FnvHashMap()), + stability_interner: RefCell::new(FnvHashMap()), + types: common_types, + named_region_map: named_region_map, + region_maps: region_maps, + free_region_maps: RefCell::new(FnvHashMap()), + item_variance_map: RefCell::new(DefIdMap()), + variance_computed: Cell::new(false), + sess: s, + def_map: def_map, + tables: RefCell::new(Tables::empty()), + impl_trait_refs: RefCell::new(DefIdMap()), + trait_defs: RefCell::new(DefIdMap()), + predicates: RefCell::new(DefIdMap()), + super_predicates: RefCell::new(DefIdMap()), + fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()), + map: map, + freevars: freevars, + tcache: RefCell::new(DefIdMap()), + rcache: RefCell::new(FnvHashMap()), + tc_cache: RefCell::new(FnvHashMap()), + ast_ty_to_ty_cache: RefCell::new(NodeMap()), + enum_var_cache: RefCell::new(DefIdMap()), + impl_or_trait_items: RefCell::new(DefIdMap()), + trait_item_def_ids: RefCell::new(DefIdMap()), + trait_items_cache: RefCell::new(DefIdMap()), + ty_param_defs: RefCell::new(NodeMap()), + normalized_cache: RefCell::new(FnvHashMap()), + lang_items: lang_items, + provided_method_sources: RefCell::new(DefIdMap()), + struct_fields: RefCell::new(DefIdMap()), + destructor_for_type: RefCell::new(DefIdMap()), + destructors: RefCell::new(DefIdSet()), + inherent_impls: RefCell::new(DefIdMap()), + impl_items: RefCell::new(DefIdMap()), + used_unsafe: RefCell::new(NodeSet()), + used_mut_nodes: RefCell::new(NodeSet()), + populated_external_types: RefCell::new(DefIdSet()), + populated_external_primitive_impls: RefCell::new(DefIdSet()), + extern_const_statics: RefCell::new(DefIdMap()), + extern_const_variants: RefCell::new(DefIdMap()), + extern_const_fns: RefCell::new(DefIdMap()), + dependency_formats: RefCell::new(FnvHashMap()), + node_lint_levels: RefCell::new(FnvHashMap()), + transmute_restrictions: RefCell::new(Vec::new()), + stability: RefCell::new(stability), + selection_cache: traits::SelectionCache::new(), + repr_hint_cache: RefCell::new(DefIdMap()), + const_qualif_map: RefCell::new(NodeMap()), + custom_coerce_unsized_kinds: RefCell::new(DefIdMap()), + cast_kinds: RefCell::new(NodeMap()), + }, f) +} + struct FlagComputation { flags: TypeFlags, @@ -3421,8 +3526,7 @@ impl<'tcx> ctxt<'tcx> { variance_computed: Cell::new(false), sess: s, def_map: def_map, - node_types: RefCell::new(FnvHashMap()), - item_substs: RefCell::new(NodeMap()), + tables: RefCell::new(Tables::empty()), impl_trait_refs: RefCell::new(DefIdMap()), trait_defs: RefCell::new(DefIdMap()), predicates: RefCell::new(DefIdMap()), @@ -3439,7 +3543,6 @@ impl<'tcx> ctxt<'tcx> { trait_item_def_ids: RefCell::new(DefIdMap()), trait_items_cache: RefCell::new(DefIdMap()), ty_param_defs: RefCell::new(NodeMap()), - adjustments: RefCell::new(NodeMap()), normalized_cache: RefCell::new(FnvHashMap()), lang_items: lang_items, provided_method_sources: RefCell::new(DefIdMap()), @@ -3452,14 +3555,10 @@ impl<'tcx> ctxt<'tcx> { used_mut_nodes: RefCell::new(NodeSet()), populated_external_types: RefCell::new(DefIdSet()), populated_external_primitive_impls: RefCell::new(DefIdSet()), - upvar_capture_map: RefCell::new(FnvHashMap()), extern_const_statics: RefCell::new(DefIdMap()), extern_const_variants: RefCell::new(DefIdMap()), extern_const_fns: RefCell::new(DefIdMap()), - method_map: RefCell::new(FnvHashMap()), dependency_formats: RefCell::new(FnvHashMap()), - closure_kinds: RefCell::new(DefIdMap()), - closure_tys: RefCell::new(DefIdMap()), node_lint_levels: RefCell::new(FnvHashMap()), transmute_restrictions: RefCell::new(Vec::new()), stability: RefCell::new(stability), @@ -3515,7 +3614,7 @@ impl<'tcx> ctxt<'tcx> { } pub fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind { - *self.closure_kinds.borrow().get(&def_id).unwrap() + *self.tables.borrow().closure_kinds.get(&def_id).unwrap() } pub fn closure_type(&self, @@ -3523,7 +3622,7 @@ impl<'tcx> ctxt<'tcx> { substs: &subst::Substs<'tcx>) -> ty::ClosureTy<'tcx> { - self.closure_tys.borrow().get(&def_id).unwrap().subst(self, substs) + self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self, substs) } pub fn type_parameter_def(&self, @@ -4369,7 +4468,7 @@ impl<'tcx> TyS<'tcx> { span: Span) -> bool { - let infcx = infer::new_infer_ctxt(param_env.tcx()); + let infcx = infer::new_infer_ctxt(param_env.tcx(), Some(param_env.clone())); let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, self, bound, span); @@ -5276,11 +5375,11 @@ impl<'tcx> ctxt<'tcx> { } pub fn node_id_to_type_opt(&self, id: ast::NodeId) -> Option<Ty<'tcx>> { - self.node_types.borrow().get(&id).cloned() + self.tables.borrow().node_types.get(&id).cloned() } pub fn node_id_item_substs(&self, id: ast::NodeId) -> ItemSubsts<'tcx> { - match self.item_substs.borrow().get(&id) { + match self.tables.borrow().item_substs.get(&id) { None => ItemSubsts::empty(), Some(ts) => ts.clone(), } @@ -5325,9 +5424,9 @@ impl<'tcx> ctxt<'tcx> { pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> { self.expr_ty(expr) .adjust(self, expr.span, expr.id, - self.adjustments.borrow().get(&expr.id), + self.tables.borrow().adjustments.get(&expr.id), |method_call| { - self.method_map.borrow().get(&method_call).map(|method| method.ty) + self.tables.borrow().method_map.get(&method_call).map(|method| method.ty) }) } @@ -6671,11 +6770,11 @@ impl<'tcx> ctxt<'tcx> { } pub fn is_method_call(&self, expr_id: ast::NodeId) -> bool { - self.method_map.borrow().contains_key(&MethodCall::expr(expr_id)) + self.tables.borrow().method_map.contains_key(&MethodCall::expr(expr_id)) } pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> { - Some(self.upvar_capture_map.borrow().get(&upvar_id).unwrap().clone()) + Some(self.tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone()) } } @@ -6689,17 +6788,21 @@ impl<'a,'tcx> Typer<'tcx> for ParameterEnvironment<'a,'tcx> { } fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> { - self.tcx.method_map.borrow().get(&method_call).map(|method| method.ty) + self.tcx.tables.borrow().method_map.get(&method_call).map(|method| method.ty) } fn node_method_origin(&self, method_call: ty::MethodCall) -> Option<ty::MethodOrigin<'tcx>> { - self.tcx.method_map.borrow().get(&method_call).map(|method| method.origin.clone()) + self.tcx.tables.borrow().method_map.get(&method_call).map(|method| method.origin.clone()) } - fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> { - &self.tcx.adjustments + fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> { + fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap<ty::AutoAdjustment<'tcx>> { + &tables.adjustments + } + + Ref::map(self.tcx.tables.borrow(), projection) } fn is_method_call(&self, id: ast::NodeId) -> bool { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index dcdf457965e..de2f33e8a4a 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -688,7 +688,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { TyStr => write!(f, "str"), TyClosure(ref did, substs) => ty::tls::with(|tcx| { try!(write!(f, "[closure")); - let closure_tys = tcx.closure_tys.borrow(); + let closure_tys = &tcx.tables.borrow().closure_tys; try!(closure_tys.get(did).map(|cty| &cty.sig).and_then(|sig| { tcx.lift(&substs).map(|substs| sig.subst(tcx, substs)) }).map(|sig| { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 8fe07da1579..db48608823d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1446,7 +1446,7 @@ impl LintPass for UnusedAllocation { _ => return } - if let Some(adjustment) = cx.tcx.adjustments.borrow().get(&e.id) { + if let Some(adjustment) = cx.tcx.tables.borrow().adjustments.get(&e.id) { if let ty::AdjustDerefRef(ty::AutoDerefRef { ref autoref, .. }) = *adjustment { match autoref { &Some(ty::AutoPtr(_, ast::MutImmutable)) => { @@ -1984,7 +1984,7 @@ impl LintPass for UnconditionalRecursion { method_id: ast::NodeId, method_name: ast::Ident, id: ast::NodeId) -> bool { - let did = match tcx.method_map.borrow().get(&ty::MethodCall::expr(id)) { + let did = match tcx.tables.borrow().method_map.get(&ty::MethodCall::expr(id)) { None => return false, Some(m) => match m.origin { // There's no way to know if a method call via a diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 24803562fa3..239141df9e8 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -904,7 +904,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { } ast::ExprMethodCall(ident, _, _) => { let method_call = MethodCall::expr(expr.id); - match self.tcx.method_map.borrow().get(&method_call) { + match self.tcx.tables.borrow().method_map.get(&method_call) { None => { self.tcx.sess.span_bug(expr.span, "method call not in \ diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index bb7e95cd4ae..dc692b0e765 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -43,6 +43,7 @@ #![feature(unicode)] #![feature(unicode)] #![feature(vec_push_all)] +#![feature(cell_extras)] #![allow(trivial_casts)] diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index 5ddad0e1947..d86242f39ce 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -886,7 +886,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { fn process_method_call(&mut self, ex: &ast::Expr, args: &Vec<P<ast::Expr>>) { - let method_map = self.tcx.method_map.borrow(); + let method_map = &self.tcx.tables.borrow().method_map; let method_callee = method_map.get(&ty::MethodCall::expr(ex.id)).unwrap(); let (def_id, decl_id) = match method_callee.origin { ty::MethodStatic(def_id) | diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index f035b32e359..0cd6bbad03a 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -212,7 +212,7 @@ pub fn self_type_for_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } pub fn kind_for_closure(ccx: &CrateContext, closure_id: ast::DefId) -> ty::ClosureKind { - *ccx.tcx().closure_kinds.borrow().get(&closure_id).unwrap() + *ccx.tcx().tables.borrow().closure_kinds.get(&closure_id).unwrap() } pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId, diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 24abe0ed3fd..dfe807d6c91 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -518,7 +518,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( let ref_ty = match node { ExprId(id) => tcx.node_id_to_type(id), MethodCallKey(method_call) => { - tcx.method_map.borrow().get(&method_call).unwrap().ty + tcx.tables.borrow().method_map.get(&method_call).unwrap().ty } }; let ref_ty = monomorphize::apply_param_substs(tcx, @@ -610,7 +610,7 @@ pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_method_call"); debug!("trans_method_call(call_expr={:?})", call_expr); let method_call = MethodCall::expr(call_expr.id); - let method_ty = match bcx.tcx().method_map.borrow().get(&method_call) { + let method_ty = match bcx.tcx().tables.borrow().method_map.get(&method_call) { Some(method) => match method.origin { ty::MethodTraitObject(_) => match method.ty.sty { ty::TyBareFn(_, ref fty) => { diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index cb30bcdbf53..b6378062855 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -130,7 +130,7 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc closure_id: ast::DefId, substs: &Substs<'tcx>) -> Option<Datum<'tcx, Rvalue>> { - if !ccx.tcx().closure_kinds.borrow().contains_key(&closure_id) { + if !ccx.tcx().tables.borrow().closure_kinds.contains_key(&closure_id) { // Not a closure. return None } diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 777b61f25f0..dc8c9242961 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -47,7 +47,7 @@ use util::nodemap::{FnvHashMap, NodeMap}; use arena::TypedArena; use libc::{c_uint, c_char}; use std::ffi::CString; -use std::cell::{Cell, RefCell}; +use std::cell::{Cell, RefCell, Ref}; use std::result::Result as StdResult; use std::vec::Vec; use syntax::ast; @@ -353,7 +353,7 @@ pub struct FunctionContext<'a, 'tcx: 'a> { // section of the executable we're generating. pub llfn: ValueRef, - // always an empty parameter-environment + // always an empty parameter-environment NOTE: @jroesch another use of ParamEnv pub param_env: ty::ParameterEnvironment<'a, 'tcx>, // The environment argument in a closure. @@ -630,8 +630,9 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> { self.tcx() - .method_map + .tables .borrow() + .method_map .get(&method_call) .map(|method| monomorphize_type(self, method.ty)) } @@ -640,18 +641,23 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { -> Option<ty::MethodOrigin<'tcx>> { self.tcx() - .method_map + .tables .borrow() + .method_map .get(&method_call) .map(|method| method.origin.clone()) } - fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> { - &self.tcx().adjustments + fn adjustments<'a>(&'a self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> { + fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) -> &'a NodeMap<ty::AutoAdjustment<'tcx>> { + &tables.adjustments + } + + Ref::map(self.tcx().tables.borrow(), project_adjustments) } fn is_method_call(&self, id: ast::NodeId) -> bool { - self.tcx().method_map.borrow().contains_key(&ty::MethodCall::expr(id)) + self.tcx().tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id)) } fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> { @@ -659,7 +665,7 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { } fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> { - Some(self.tcx().upvar_capture_map.borrow().get(&upvar_id).unwrap().clone()) + Some(self.tcx().tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone()) } fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool { @@ -991,7 +997,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, trait_ref, trait_ref.def_id()); tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id()); - let infcx = infer::new_infer_ctxt(tcx); + let infcx = infer::new_infer_ctxt(tcx, None); // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. @@ -1053,7 +1059,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, predicates); let tcx = ccx.tcx(); - let infcx = infer::new_infer_ctxt(tcx); + let infcx = infer::new_infer_ctxt(tcx, None); let typer = NormalizingClosureTyper::new(tcx); let mut selcx = traits::SelectionContext::new(&infcx, &typer); let mut fulfill_cx = traits::FulfillmentContext::new(false); @@ -1070,6 +1076,10 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()).is_ok() } +// NOTE: here is another use of parameter environment without an InferCtxt, +// this is obviously related to the typer interface requiring a parameter env. +// We should pay attention to this when refactoring +// - @jroesch pub struct NormalizingClosureTyper<'a,'tcx:'a> { param_env: ty::ParameterEnvironment<'a, 'tcx> } @@ -1191,7 +1201,7 @@ pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, tcx.node_id_item_substs(id).substs } MethodCallKey(method_call) => { - tcx.method_map.borrow().get(&method_call).unwrap().substs.clone() + tcx.tables.borrow().method_map.get(&method_call).unwrap().substs.clone() } }; diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 8ec60000ee8..57af688ef60 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -228,7 +228,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let def = ccx.tcx().def_map.borrow().get(&expr.id).unwrap().full_def(); match def { def::DefConst(def_id) | def::DefAssociatedConst(def_id, _) => { - if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) { + if !ccx.tcx().tables.borrow().adjustments.contains_key(&expr.id) { debug!("get_const_expr_as_global ({:?}): found const {:?}", expr.id, def_id); return get_const_val(ccx, def_id, expr); @@ -281,7 +281,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let mut llconst = llconst; let mut ety_adjusted = monomorphize::apply_param_substs(cx.tcx(), param_substs, &cx.tcx().expr_ty_adjusted(e)); - let opt_adj = cx.tcx().adjustments.borrow().get(&e.id).cloned(); + let opt_adj = cx.tcx().tables.borrow().adjustments.get(&e.id).cloned(); match opt_adj { Some(ty::AdjustReifyFnPointer) => { // FIXME(#19925) once fn item types are @@ -894,7 +894,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ast::ExprMethodCall(_, _, ref args) => { let arg_vals = map_list(args); let method_call = ty::MethodCall::expr(e.id); - let method_did = match cx.tcx().method_map.borrow()[&method_call].origin { + let method_did = match cx.tcx().tables.borrow().method_map[&method_call].origin { ty::MethodStatic(did) => did, _ => cx.sess().span_bug(e.span, "expected a const method def") }; diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 8fd88055b8e..045cc69bf95 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -117,7 +117,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debuginfo::set_source_location(bcx.fcx, expr.id, expr.span); - if bcx.tcx().adjustments.borrow().contains_key(&expr.id) { + if bcx.tcx().tables.borrow().adjustments.contains_key(&expr.id) { // use trans, which may be less efficient but // which will perform the adjustments: let datum = unpack_datum!(bcx, trans(bcx, expr)); @@ -345,7 +345,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, { let mut bcx = bcx; let mut datum = datum; - let adjustment = match bcx.tcx().adjustments.borrow().get(&expr.id).cloned() { + let adjustment = match bcx.tcx().tables.borrow().adjustments.get(&expr.id).cloned() { None => { return DatumBlock::new(bcx, datum); } @@ -372,7 +372,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Don't skip a conversion from Box<T> to &T, etc. ty::TyRef(..) => { let method_call = MethodCall::autoderef(expr.id, 0); - if bcx.tcx().method_map.borrow().contains_key(&method_call) { + if bcx.tcx().tables.borrow().method_map.contains_key(&method_call) { // Don't skip an overloaded deref. 0 } else { @@ -774,8 +774,9 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Check for overloaded index. let method_ty = ccx.tcx() - .method_map + .tables .borrow() + .method_map .get(&method_call) .map(|method| method.ty); let elt_datum = match method_ty { @@ -1617,7 +1618,7 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Otherwise, we should be in the RvalueDpsExpr path. assert!( op == ast::UnDeref || - !ccx.tcx().method_map.borrow().contains_key(&method_call)); + !ccx.tcx().tables.borrow().method_map.contains_key(&method_call)); let un_ty = expr_ty(bcx, expr); @@ -1910,7 +1911,7 @@ fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let ccx = bcx.ccx(); // if overloaded, would be RvalueDpsExpr - assert!(!ccx.tcx().method_map.borrow().contains_key(&MethodCall::expr(expr.id))); + assert!(!ccx.tcx().tables.borrow().method_map.contains_key(&MethodCall::expr(expr.id))); match op.node { ast::BiAnd => { @@ -1950,7 +1951,12 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, dest: Option<Dest>, autoref: bool) -> Result<'blk, 'tcx> { - let method_ty = bcx.tcx().method_map.borrow().get(&method_call).unwrap().ty; + let method_ty = bcx.tcx() + .tables + .borrow() + .method_map + .get(&method_call).unwrap().ty; + callee::trans_call_inner(bcx, expr.debug_loc(), monomorphize_type(bcx, method_ty), @@ -1973,8 +1979,9 @@ fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, debug!("trans_overloaded_call {}", expr.id); let method_call = MethodCall::expr(expr.id); let method_type = bcx.tcx() - .method_map + .tables .borrow() + .method_map .get(&method_call) .unwrap() .ty; @@ -2154,7 +2161,7 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debug!("trans_assign_op(expr={:?})", expr); // User-defined operator methods cannot be used with `+=` etc right now - assert!(!bcx.tcx().method_map.borrow().contains_key(&MethodCall::expr(expr.id))); + assert!(!bcx.tcx().tables.borrow().method_map.contains_key(&MethodCall::expr(expr.id))); // Evaluate LHS (destination), which should be an lvalue let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op")); @@ -2229,8 +2236,12 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let mut bcx = bcx; // Check for overloaded deref. - let method_ty = ccx.tcx().method_map.borrow() + let method_ty = ccx.tcx() + .tables + .borrow() + .method_map .get(&method_call).map(|method| method.ty); + let datum = match method_ty { Some(method_ty) => { let method_ty = monomorphize_type(bcx, method_ty); @@ -2615,7 +2626,7 @@ enum ExprKind { } fn expr_kind(tcx: &ty::ctxt, expr: &ast::Expr) -> ExprKind { - if tcx.method_map.borrow().contains_key(&MethodCall::expr(expr.id)) { + if tcx.tables.borrow().method_map.contains_key(&MethodCall::expr(expr.id)) { // Overloaded operations are generally calls, and hence they are // generated via DPS, but there are a few exceptions: return match expr.node { diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index a3e5b640fd0..e46c3b5fab1 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -109,11 +109,13 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("meth::trans_method_callee"); let (origin, method_ty) = - bcx.tcx().method_map - .borrow() - .get(&method_call) - .map(|method| (method.origin.clone(), method.ty)) - .unwrap(); + bcx.tcx() + .tables + .borrow() + .method_map + .get(&method_call) + .map(|method| (method.origin.clone(), method.ty)) + .unwrap(); match origin { ty::MethodStatic(did) | diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index cae810c9082..fa992511cc1 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -322,8 +322,9 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T } // FIXME(#20304) -- cache - - let infcx = infer::new_infer_ctxt(tcx); + // NOTE: @jroesch + // Here is of an example where we do not use a param_env but use a typer instead. + let infcx = infer::new_infer_ctxt(tcx, None); let typer = NormalizingClosureTyper::new(tcx); let mut selcx = traits::SelectionContext::new(&infcx, &typer); let cause = traits::ObligationCause::dummy(); diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7109e45b552..c2170686fac 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -324,7 +324,7 @@ fn write_overloaded_call_method_map<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>, call_expr: &ast::Expr, method_callee: ty::MethodCallee<'tcx>) { let method_call = ty::MethodCall::expr(call_expr.id); - fcx.inh.method_map.borrow_mut().insert(method_call, method_callee); + fcx.inh.tables.borrow_mut().method_map.insert(method_call, method_callee); } #[derive(Debug)] diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index d431c0fda98..b5ee46ece94 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -61,7 +61,7 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expected_sig); let closure_type = fcx.ccx.tcx.mk_closure(expr_def_id, - fcx.ccx.tcx.mk_substs(fcx.inh.param_env.free_substs.clone())); + fcx.ccx.tcx.mk_substs(fcx.inh.infcx.parameter_environment.free_substs.clone())); fcx.write_ty(expr.id, closure_type); @@ -86,9 +86,9 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, fn_ty.sig, opt_kind); - fcx.inh.closure_tys.borrow_mut().insert(expr_def_id, fn_ty); + fcx.inh.tables.borrow_mut().closure_tys.insert(expr_def_id, fn_ty); match opt_kind { - Some(kind) => { fcx.inh.closure_kinds.borrow_mut().insert(expr_def_id, kind); } + Some(kind) => { fcx.inh.tables.borrow_mut().closure_kinds.insert(expr_def_id, kind); } None => { } } } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 349d1a8bb65..dc8ef46a7ba 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -43,7 +43,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, debug!("compare_impl_method: impl_trait_ref (liberated) = {:?}", impl_trait_ref); - let infcx = infer::new_infer_ctxt(tcx); + let mut infcx = infer::new_infer_ctxt(tcx, None); let mut fulfillment_cx = traits::FulfillmentContext::new(true); let trait_to_impl_substs = &impl_trait_ref.substs; @@ -240,11 +240,13 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.into_vec()); let trait_param_env = traits::normalize_param_env_or_error(trait_param_env, normalize_cause.clone()); + // TODO (@jroesch) this seems ugly, but is a temporary change + infcx.parameter_environment = trait_param_env; debug!("compare_impl_method: trait_bounds={:?}", - trait_param_env.caller_bounds); + infcx.parameter_environment.caller_bounds); - let mut selcx = traits::SelectionContext::new(&infcx, &trait_param_env); + let mut selcx = traits::SelectionContext::new(&infcx, &infcx.parameter_environment); for predicate in impl_pred.fns { let traits::Normalized { value: predicate, .. } = @@ -345,7 +347,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, // Check that all obligations are satisfied by the implementation's // version. - match fulfillment_cx.select_all_or_error(&infcx, &trait_param_env) { + match fulfillment_cx.select_all_or_error(&infcx, &infcx.parameter_environment) { Err(ref errors) => { traits::report_fulfillment_errors(&infcx, errors) } Ok(_) => {} } @@ -360,7 +362,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, // anyway, so it shouldn't be needed there either. Anyway, we can // always add more relations later (it's backwards compat). let mut free_regions = FreeRegionMap::new(); - free_regions.relate_free_regions_from_predicates(tcx, &trait_param_env.caller_bounds); + free_regions.relate_free_regions_from_predicates(tcx, &infcx.parameter_environment.caller_bounds); infcx.resolve_regions_and_report_errors(&free_regions, impl_m_body_id); @@ -416,7 +418,7 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>, debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); - let infcx = infer::new_infer_ctxt(tcx); + let infcx = infer::new_infer_ctxt(tcx, None); let mut fulfillment_cx = traits::FulfillmentContext::new(true); // 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 a48cffb4472..4abfd84d8ef 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -93,7 +93,8 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( ty: named_type } = tcx.lookup_item_type(self_type_did); - let infcx = infer::new_infer_ctxt(tcx); + let infcx = infer::new_infer_ctxt(tcx, None); + infcx.commit_if_ok(|snapshot| { let (named_type_to_skolem, skol_map) = infcx.construct_skolemized_subst(named_type_generics, snapshot); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 5f7a78ec611..5601888a1f0 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -488,8 +488,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // Count autoderefs. let autoderef_count = match self.fcx .inh - .adjustments + .tables .borrow() + .adjustments .get(&expr.id) { Some(&ty::AdjustDerefRef(ref adj)) => adj.autoderefs, Some(_) | None => 0, @@ -527,7 +528,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // expects. This is annoying and horrible. We // ought to recode this routine so it doesn't // (ab)use the normal type checking paths. - let adj = self.fcx.inh.adjustments.borrow().get(&base_expr.id).cloned(); + let adj = self.fcx.inh.tables.borrow().adjustments.get(&base_expr.id).cloned(); let (autoderefs, unsize) = match adj { Some(ty::AdjustDerefRef(adr)) => match adr.autoref { None => { @@ -589,7 +590,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // if this is an overloaded deref, then re-evaluate with // a preference for mut let method_call = MethodCall::expr(expr.id); - if self.fcx.inh.method_map.borrow().contains_key(&method_call) { + if self.fcx.inh.tables.borrow().method_map.contains_key(&method_call) { check::try_overloaded_deref( self.fcx, expr.span, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 8026fce69ec..2cf04191914 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -477,7 +477,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // FIXME -- Do we want to commit to this behavior for param bounds? let bounds: Vec<_> = - self.fcx.inh.param_env.caller_bounds + self.fcx.inh.infcx.parameter_environment.caller_bounds .iter() .filter_map(|predicate| { match *predicate { @@ -742,7 +742,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { _ => continue, }; - let closure_kinds = self.fcx.inh.closure_kinds.borrow(); + let closure_kinds = &self.fcx.inh.tables.borrow().closure_kinds; let closure_kind = match closure_kinds.get(&closure_def_id) { Some(&k) => k, None => { @@ -845,7 +845,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { debug!("assemble_where_clause_candidates(trait_def_id={:?})", trait_def_id); - let caller_predicates = self.fcx.inh.param_env.caller_bounds.clone(); + let caller_predicates = self.fcx.inh.infcx.parameter_environment.caller_bounds.clone(); for poly_bound in traits::elaborate_predicates(self.tcx(), caller_predicates) .filter_map(|p| p.to_opt_poly_trait_ref()) .filter(|b| b.def_id() == trait_def_id) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 299ccd579cc..058cbe020b7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -97,7 +97,7 @@ use middle::traits::{self, report_fulfillment_errors}; use middle::ty::{FnSig, GenericPredicates, TypeScheme}; use middle::ty::{Disr, ParamTy, ParameterEnvironment}; use middle::ty::{self, HasTypeFlags, RegionEscape, ToPolyTraitRef, Ty}; -use middle::ty::{MethodCall, MethodCallee, MethodMap}; +use middle::ty::{MethodCall, MethodCallee}; use middle::ty_fold::{TypeFolder, TypeFoldable}; use rscope::RegionScope; use session::Session; @@ -152,16 +152,8 @@ mod op; pub struct Inherited<'a, 'tcx: 'a> { infcx: infer::InferCtxt<'a, 'tcx>, locals: RefCell<NodeMap<Ty<'tcx>>>, - param_env: ty::ParameterEnvironment<'a, 'tcx>, - // Temporary tables: - node_types: RefCell<NodeMap<Ty<'tcx>>>, - item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>, - adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>, - method_map: MethodMap<'tcx>, - upvar_capture_map: RefCell<ty::UpvarCaptureMap>, - closure_tys: RefCell<DefIdMap<ty::ClosureTy<'tcx>>>, - closure_kinds: RefCell<DefIdMap<ty::ClosureKind>>, + tables: &'a RefCell<ty::Tables<'tcx>>, // A mapping from each fn's id to its signature, with all bound // regions replaced with free ones. Unlike the other tables, this @@ -303,52 +295,68 @@ impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> { let ty = self.node_ty(id); self.resolve_type_vars_or_error(&ty) } + fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> { - let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id)); + let ty = self.adjust_expr_ty(expr, self.inh.tables.borrow().adjustments.get(&expr.id)); self.resolve_type_vars_or_error(&ty) } + fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool { let ty = self.infcx().resolve_type_vars_if_possible(&ty); !traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span) } + fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> { - self.inh.method_map.borrow() - .get(&method_call) - .map(|method| method.ty) - .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty)) + self.inh.tables + .borrow() + .method_map + .get(&method_call) + .map(|method| method.ty) + .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty)) } + fn node_method_origin(&self, method_call: ty::MethodCall) -> Option<ty::MethodOrigin<'tcx>> { - self.inh.method_map.borrow() - .get(&method_call) - .map(|method| method.origin.clone()) + self.inh.tables + .borrow() + .method_map + .get(&method_call) + .map(|method| method.origin.clone()) } - fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> { - &self.inh.adjustments + + fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> { + fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) -> &'a NodeMap<ty::AutoAdjustment<'tcx>> { + &tables.adjustments + } + + Ref::map(self.inh.tables.borrow(), project_adjustments) } + fn is_method_call(&self, id: ast::NodeId) -> bool { - self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id)) + self.inh.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id)) } + fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> { self.param_env().temporary_scope(rvalue_id) } + fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> { - self.inh.upvar_capture_map.borrow().get(&upvar_id).cloned() + self.inh.tables.borrow().upvar_capture_map.get(&upvar_id).cloned() } } impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> { fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> { - &self.inh.param_env + &self.inh.infcx.parameter_environment } fn closure_kind(&self, def_id: ast::DefId) -> Option<ty::ClosureKind> { - self.inh.closure_kinds.borrow().get(&def_id).cloned() + self.inh.tables.borrow().closure_kinds.get(&def_id).cloned() } fn closure_type(&self, @@ -356,7 +364,7 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> { substs: &subst::Substs<'tcx>) -> ty::ClosureTy<'tcx> { - self.inh.closure_tys.borrow().get(&def_id).unwrap().subst(self.tcx(), substs) + self.inh.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self.tcx(), substs) } fn closure_upvars(&self, @@ -369,19 +377,14 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> { impl<'a, 'tcx> Inherited<'a, 'tcx> { fn new(tcx: &'a ty::ctxt<'tcx>, + tables: &'a RefCell<ty::Tables<'tcx>>, param_env: ty::ParameterEnvironment<'a, 'tcx>) -> Inherited<'a, 'tcx> { + Inherited { - infcx: infer::new_infer_ctxt(tcx), + infcx: infer::new_infer_ctxt(tcx, Some(param_env)), locals: RefCell::new(NodeMap()), - param_env: param_env, - node_types: RefCell::new(NodeMap()), - item_substs: RefCell::new(NodeMap()), - adjustments: RefCell::new(NodeMap()), - method_map: RefCell::new(FnvHashMap()), - upvar_capture_map: RefCell::new(FnvHashMap()), - closure_tys: RefCell::new(DefIdMap()), - closure_kinds: RefCell::new(DefIdMap()), + tables: tables, fn_sig_map: RefCell::new(NodeMap()), fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(true)), deferred_call_resolutions: RefCell::new(DefIdMap()), @@ -424,12 +427,12 @@ pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, } } -fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>) +fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, tables: &'a RefCell<ty::Tables<'tcx>>) -> Inherited<'a, 'tcx> { // It's kind of a kludge to manufacture a fake function context // and statement context, but we might as well do write the code only once let param_env = ccx.tcx.empty_parameter_environment(); - Inherited::new(ccx.tcx, param_env) + Inherited::new(ccx.tcx, &tables, param_env) } struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } @@ -504,16 +507,20 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, { match raw_fty.sty { ty::TyBareFn(_, ref fn_ty) => { - let inh = Inherited::new(ccx.tcx, param_env); + let tables = RefCell::new(ty::Tables::empty()); + let inh = Inherited::new(ccx.tcx, &tables, param_env); // Compute the fty from point of view of inside fn. let fn_sig = - fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs); + fn_ty.sig.subst(ccx.tcx, &inh.infcx.parameter_environment.free_substs); let fn_sig = ccx.tcx.liberate_late_bound_regions(region::DestructionScopeData::new(body.id), &fn_sig); let fn_sig = - inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig); + inh.normalize_associated_types_in(&inh.infcx.parameter_environment, + body.span, + body.id, + &fn_sig); let fcx = check_fn(ccx, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body, &inh); @@ -1198,7 +1205,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { } fn get_free_substs(&self) -> Option<&Substs<'tcx>> { - Some(&self.inh.param_env.free_substs) + Some(&self.inh.infcx.parameter_environment.free_substs) } fn get_type_parameter_bounds(&self, @@ -1207,7 +1214,8 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported> { let def = self.tcx().type_parameter_def(node_id); - let r = self.inh.param_env.caller_bounds + let r = self.inh.infcx.parameter_environment + .caller_bounds .iter() .filter_map(|predicate| { match *predicate { @@ -1273,7 +1281,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> { - &self.inh.param_env + &self.inh.infcx.parameter_environment } pub fn sess(&self) -> &Session { @@ -1368,7 +1376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64. pub fn default_type_parameters(&self) { use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither}; - for (_, &mut ref ty) in &mut *self.inh.node_types.borrow_mut() { + for (_, &mut ref ty) in &mut self.inh.tables.borrow_mut().node_types { let resolved = self.infcx().resolve_type_vars_if_possible(ty); if self.infcx().type_var_diverges(resolved) { demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil()); @@ -1390,7 +1398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) { debug!("write_ty({}, {:?}) in fcx {}", node_id, ty, self.tag()); - self.inh.node_types.borrow_mut().insert(node_id, ty); + self.inh.tables.borrow_mut().node_types.insert(node_id, ty); } pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) { @@ -1400,7 +1408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { substs, self.tag()); - self.inh.item_substs.borrow_mut().insert(node_id, substs); + self.inh.tables.borrow_mut().item_substs.insert(node_id, substs); } } @@ -1426,7 +1434,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } - self.inh.adjustments.borrow_mut().insert(node_id, adj); + self.inh.tables.borrow_mut().adjustments.insert(node_id, adj); } /// Basically whenever we are converting from a type scheme into @@ -1627,7 +1635,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> { - match self.inh.node_types.borrow().get(&ex.id) { + match self.inh.tables.borrow().node_types.get(&ex.id) { Some(&t) => t, None => { self.tcx().sess.bug(&format!("no type for expr in fcx {}", @@ -1646,13 +1654,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let raw_ty = self.infcx().shallow_resolve(raw_ty); let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty); raw_ty.adjust(self.tcx(), expr.span, expr.id, adjustment, |method_call| { - self.inh.method_map.borrow().get(&method_call) + self.inh.tables.borrow().method_map.get(&method_call) .map(|method| resolve_ty(method.ty)) }) } pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> { - match self.inh.node_types.borrow().get(&id) { + match self.inh.tables.borrow().node_types.get(&id) { Some(&t) => t, None if self.err_count_since_creation() != 0 => self.tcx().types.err, None => { @@ -1665,7 +1673,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> { - self.inh.item_substs.borrow() + // NOTE: @jroesch this is hack that appears to be fixed on nightly, will monitor if it changes + // when we upgrade the snapshot compiler + fn project_item_susbts<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) -> &'a NodeMap<ty::ItemSubsts<'tcx>> { + &tables.item_substs + } + + Ref::map(self.inh.tables.borrow(), project_item_susbts) } pub fn opt_node_ty_substs<F>(&self, @@ -1673,7 +1687,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { f: F) where F: FnOnce(&ty::ItemSubsts<'tcx>), { - match self.inh.item_substs.borrow().get(&id) { + match self.inh.tables.borrow().item_substs.get(&id) { Some(s) => { f(s) } None => { } } @@ -2039,7 +2053,7 @@ fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let ret_ty = fcx.tcx().no_late_bound_regions(&ret_ty).unwrap().unwrap(); if let Some(method_call) = method_call { - fcx.inh.method_map.borrow_mut().insert(method_call, method); + fcx.inh.tables.borrow_mut().method_map.insert(method_call, method); } // method returns &T, but the type as visible to user is T, so deref @@ -2640,7 +2654,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, Ok(method) => { let method_ty = method.ty; let method_call = MethodCall::expr(expr.id); - fcx.inh.method_map.borrow_mut().insert(method_call, method); + fcx.inh.tables.borrow_mut().method_map.insert(method_call, method); method_ty } Err(error) => { @@ -4074,7 +4088,8 @@ fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>, expr: &'tcx ast::Expr, expected_type: Ty<'tcx>) { - let inh = static_inherited_fields(ccx); + let tables = RefCell::new(ty::Tables::empty()); + let inh = static_inherited_fields(ccx, &tables); let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id); check_const_with_ty(&fcx, expr.span, expr, expected_type); } @@ -4083,7 +4098,8 @@ fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, sp: Span, e: &'tcx ast::Expr, id: ast::NodeId) { - let inh = static_inherited_fields(ccx); + let tables = RefCell::new(ty::Tables::empty()); + let inh = static_inherited_fields(ccx, &tables); let rty = ccx.tcx.node_id_to_type(id); let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id); let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).unwrap().ty; @@ -4235,7 +4251,8 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let rty = ccx.tcx.node_id_to_type(id); let mut disr_vals: Vec<ty::Disr> = Vec::new(); - let inh = static_inherited_fields(ccx); + let tables = RefCell::new(ty::Tables::empty()); + let inh = static_inherited_fields(ccx, &tables); let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id); let (_, repr_type_ty) = ccx.tcx.enum_repr_type(Some(&hint)); diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 5a114c81119..c419a986f95 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -330,7 +330,7 @@ fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, // HACK(eddyb) Fully qualified path to work around a resolve bug. let method_call = ::middle::ty::MethodCall::expr(expr.id); - fcx.inh.method_map.borrow_mut().insert(method_call, method); + fcx.inh.tables.borrow_mut().method_map.insert(method_call, method); // extract return type for method; all late bound regions // should have been instantiated by now @@ -454,4 +454,3 @@ fn is_builtin_binop<'tcx>(cx: &ty::ctxt<'tcx>, } } } - diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 13961834aeb..8f8ec0f7264 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -124,7 +124,7 @@ pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) { pub fn regionck_item(fcx: &FnCtxt, item: &ast::Item) { let mut rcx = Rcx::new(fcx, RepeatingScope(item.id), item.id, Subject(item.id)); let tcx = fcx.tcx(); - rcx.free_region_map.relate_free_regions_from_predicates(tcx, &fcx.inh.param_env.caller_bounds); + rcx.free_region_map.relate_free_regions_from_predicates(tcx, &fcx.inh.infcx.parameter_environment.caller_bounds); rcx.visit_region_obligations(item.id); rcx.resolve_regions_and_report_errors(); } @@ -143,7 +143,7 @@ pub fn regionck_fn(fcx: &FnCtxt, } let tcx = fcx.tcx(); - rcx.free_region_map.relate_free_regions_from_predicates(tcx, &fcx.inh.param_env.caller_bounds); + rcx.free_region_map.relate_free_regions_from_predicates(tcx, &fcx.inh.infcx.parameter_environment.caller_bounds); rcx.resolve_regions_and_report_errors(); @@ -254,7 +254,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { } fn resolve_method_type(&self, method_call: MethodCall) -> Option<Ty<'tcx>> { - let method_ty = self.fcx.inh.method_map.borrow() + let method_ty = self.fcx.inh.tables.borrow().method_map .get(&method_call).map(|method| method.ty); method_ty.map(|method_ty| self.resolve_type(method_ty)) } @@ -267,7 +267,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { } else { ty_unadjusted.adjust( self.fcx.tcx(), expr.span, expr.id, - self.fcx.inh.adjustments.borrow().get(&expr.id), + self.fcx.inh.tables.borrow().adjustments.get(&expr.id), |method_call| self.resolve_method_type(method_call)) } } @@ -511,12 +511,13 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { expr_ty, ty::ReScope(CodeExtent::from_node_id(expr.id))); let method_call = MethodCall::expr(expr.id); - let has_method_map = rcx.fcx.inh.method_map.borrow().contains_key(&method_call); + let has_method_map = rcx.fcx.inh.tables.borrow().method_map.contains_key(&method_call); // Check any autoderefs or autorefs that appear. - if let Some(adjustment) = rcx.fcx.inh.adjustments.borrow().get(&expr.id) { + let adjustment = rcx.fcx.inh.tables.borrow().adjustments.get(&expr.id).map(|a| a.clone()); + if let Some(adjustment) = adjustment { debug!("adjustment={:?}", adjustment); - match *adjustment { + match adjustment { ty::AdjustDerefRef(ty::AutoDerefRef {autoderefs, ref autoref, ..}) => { let expr_ty = rcx.resolve_node_type(expr.id); constrain_autoderefs(rcx, expr, autoderefs, expr_ty); @@ -657,7 +658,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { ast::ExprUnary(ast::UnDeref, ref base) => { // For *a, the lifetime of a must enclose the deref let method_call = MethodCall::expr(expr.id); - let base_ty = match rcx.fcx.inh.method_map.borrow().get(&method_call) { + let base_ty = match rcx.fcx.inh.tables.borrow().method_map.get(&method_call) { Some(method) => { constrain_call(rcx, expr, Some(&**base), None::<ast::Expr>.iter(), true); @@ -884,7 +885,9 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, let method_call = MethodCall::autoderef(deref_expr.id, i as u32); debug!("constrain_autoderefs: method_call={:?} (of {:?} total)", method_call, derefs); - derefd_ty = match rcx.fcx.inh.method_map.borrow().get(&method_call) { + let method = rcx.fcx.inh.tables.borrow().method_map.get(&method_call).map(|m| m.clone()); + + derefd_ty = match method { Some(method) => { debug!("constrain_autoderefs: #{} is overloaded, method={:?}", i, method); @@ -1018,7 +1021,7 @@ fn type_of_node_must_outlive<'a, 'tcx>( // report errors later on in the writeback phase. let ty0 = rcx.resolve_node_type(id); let ty = ty0.adjust(tcx, origin.span(), id, - rcx.fcx.inh.adjustments.borrow().get(&id), + rcx.fcx.inh.tables.borrow().adjustments.get(&id), |method_call| rcx.resolve_method_type(method_call)); debug!("constrain_regions_in_type_of_node(\ ty={}, ty0={}, id={}, minimum_lifetime={:?})", @@ -1292,7 +1295,7 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, // Detect by-ref upvar `x`: let cause = match note { mc::NoteUpvarRef(ref upvar_id) => { - let upvar_capture_map = rcx.fcx.inh.upvar_capture_map.borrow_mut(); + let upvar_capture_map = &rcx.fcx.inh.tables.borrow_mut().upvar_capture_map; match upvar_capture_map.get(upvar_id) { Some(&ty::UpvarCapture::ByRef(ref upvar_borrow)) => { // The mutability of the upvar may have been modified @@ -1453,7 +1456,7 @@ fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, origin: infer::SubregionOrigin<'tcx>, region: ty::Region, generic: &GenericKind<'tcx>) { - let param_env = &rcx.fcx.inh.param_env; + let param_env = &rcx.fcx.inh.infcx.parameter_environment; debug!("param_must_outlive(region={:?}, generic={:?})", region, diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 1345f322476..db32b29ebab 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -129,9 +129,9 @@ impl<'a,'tcx> SeedBorrowKind<'a,'tcx> { _body: &ast::Block) { let closure_def_id = ast_util::local_def(expr.id); - if !self.fcx.inh.closure_kinds.borrow().contains_key(&closure_def_id) { + if !self.fcx.inh.tables.borrow().closure_kinds.contains_key(&closure_def_id) { self.closures_with_inferred_kinds.insert(expr.id); - self.fcx.inh.closure_kinds.borrow_mut().insert(closure_def_id, ty::FnClosureKind); + self.fcx.inh.tables.borrow_mut().closure_kinds.insert(closure_def_id, ty::FnClosureKind); debug!("check_closure: adding closure_id={:?} to closures_with_inferred_kinds", closure_def_id); } @@ -156,7 +156,7 @@ impl<'a,'tcx> SeedBorrowKind<'a,'tcx> { } }; - self.fcx.inh.upvar_capture_map.borrow_mut().insert(upvar_id, capture_kind); + self.fcx.inh.tables.borrow_mut().upvar_capture_map.insert(upvar_id, capture_kind); } }); } @@ -267,7 +267,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { // to move out of an upvar, this must be a FnOnce closure self.adjust_closure_kind(upvar_id.closure_expr_id, ty::FnOnceClosureKind); - let mut upvar_capture_map = self.fcx.inh.upvar_capture_map.borrow_mut(); + let upvar_capture_map = &mut self.fcx.inh.tables.borrow_mut().upvar_capture_map; upvar_capture_map.insert(upvar_id, ty::UpvarCapture::ByValue); } mc::NoteClosureEnv(upvar_id) => { @@ -374,9 +374,11 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { // upvar, then we need to modify the // borrow_kind of the upvar to make sure it // is inferred to mutable if necessary - let mut upvar_capture_map = self.fcx.inh.upvar_capture_map.borrow_mut(); - let ub = upvar_capture_map.get_mut(&upvar_id).unwrap(); - self.adjust_upvar_borrow_kind(upvar_id, ub, borrow_kind); + { + let upvar_capture_map = &mut self.fcx.inh.tables.borrow_mut().upvar_capture_map; + let ub = upvar_capture_map.get_mut(&upvar_id).unwrap(); + self.adjust_upvar_borrow_kind(upvar_id, ub, borrow_kind); + } // also need to be in an FnMut closure since this is not an ImmBorrow self.adjust_closure_kind(upvar_id.closure_expr_id, ty::FnMutClosureKind); @@ -442,7 +444,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { } let closure_def_id = ast_util::local_def(closure_id); - let mut closure_kinds = self.fcx.inh.closure_kinds.borrow_mut(); + let closure_kinds = &mut self.fcx.inh.tables.borrow_mut().closure_kinds; let existing_kind = *closure_kinds.get(&closure_def_id).unwrap(); debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}", diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 00bbbafd5cd..c2852e425b6 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -18,6 +18,7 @@ use middle::traits; use middle::ty::{self, Ty}; use middle::ty_fold::{TypeFolder, TypeFoldable, super_fold_ty}; +use std::cell::RefCell; use std::collections::HashSet; use syntax::ast; use syntax::ast_util::local_def; @@ -143,7 +144,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { &type_scheme.generics, &type_predicates, item.id); - let inh = Inherited::new(ccx.tcx, param_env); + let tables = RefCell::new(ty::Tables::empty()); + let inh = Inherited::new(ccx.tcx, &tables, param_env); let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(type_scheme.ty), item.id); f(self, &fcx); fcx.select_all_obligations_or_error(); @@ -199,7 +201,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { let type_scheme = fcx.tcx().lookup_item_type(local_def(item.id)); let item_ty = fcx.instantiate_type_scheme(item.span, - &fcx.inh.param_env.free_substs, + &fcx.inh.infcx.parameter_environment.free_substs, &type_scheme.ty); bounds_checker.check_traits_in_ty(item_ty, item.span); @@ -220,7 +222,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { // to free. let self_ty = fcx.tcx().node_id_to_type(item.id); let self_ty = fcx.instantiate_type_scheme(item.span, - &fcx.inh.param_env.free_substs, + &fcx.inh.infcx.parameter_environment.free_substs, &self_ty); bounds_checker.check_traits_in_ty(self_ty, item.span); @@ -233,7 +235,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { }; let trait_ref = fcx.instantiate_type_scheme(item.span, - &fcx.inh.param_env.free_substs, + &fcx.inh.infcx.parameter_environment.free_substs, &trait_ref); // We are stricter on the trait-ref in an impl than the @@ -635,7 +637,7 @@ fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, .map(|field| { let field_ty = fcx.tcx().node_id_to_type(field.node.id); let field_ty = fcx.instantiate_type_scheme(field.span, - &fcx.inh.param_env.free_substs, + &fcx.inh.infcx.parameter_environment.free_substs, &field_ty); AdtField { ty: field_ty, span: field.span } }) @@ -660,7 +662,7 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let arg_ty = arg_tys[index]; let arg_ty = fcx.instantiate_type_scheme(variant.span, - &fcx.inh.param_env.free_substs, + &fcx.inh.infcx.parameter_environment.free_substs, &arg_ty); AdtField { ty: arg_ty, diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 29119f3b594..d9906979496 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -96,14 +96,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty); if lhs_ty.is_scalar() && rhs_ty.is_scalar() { - self.fcx.inh.method_map.borrow_mut().remove(&MethodCall::expr(e.id)); + self.fcx.inh.tables.borrow_mut().method_map.remove(&MethodCall::expr(e.id)); // weird but true: the by-ref binops put an // adjustment on the lhs but not the rhs; the // adjustment for rhs is kind of baked into the // system. if !ast_util::is_by_value_binop(op.node) { - self.fcx.inh.adjustments.borrow_mut().remove(&lhs.id); + self.fcx.inh.tables.borrow_mut().adjustments.remove(&lhs.id); } } } @@ -204,7 +204,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { return; } - for (upvar_id, upvar_capture) in self.fcx.inh.upvar_capture_map.borrow().iter() { + for (upvar_id, upvar_capture) in self.fcx.inh.tables.borrow().upvar_capture_map.iter() { let new_upvar_capture = match *upvar_capture { ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, ty::UpvarCapture::ByRef(ref upvar_borrow) => { @@ -217,7 +217,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { debug!("Upvar capture for {:?} resolved to {:?}", upvar_id, new_upvar_capture); - self.fcx.tcx().upvar_capture_map.borrow_mut().insert(*upvar_id, new_upvar_capture); + self.fcx.tcx().tables.borrow_mut().upvar_capture_map.insert(*upvar_id, new_upvar_capture); } } @@ -226,13 +226,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { return } - for (def_id, closure_ty) in self.fcx.inh.closure_tys.borrow().iter() { + for (def_id, closure_ty) in self.fcx.inh.tables.borrow().closure_tys.iter() { let closure_ty = self.resolve(closure_ty, ResolvingClosure(*def_id)); - self.fcx.tcx().closure_tys.borrow_mut().insert(*def_id, closure_ty); + self.fcx.tcx().tables.borrow_mut().closure_tys.insert(*def_id, closure_ty); } - for (def_id, &closure_kind) in self.fcx.inh.closure_kinds.borrow().iter() { - self.fcx.tcx().closure_kinds.borrow_mut().insert(*def_id, closure_kind); + for (def_id, &closure_kind) in self.fcx.inh.tables.borrow().closure_kinds.iter() { + self.fcx.tcx().tables.borrow_mut().closure_kinds.insert(*def_id, closure_kind); } } @@ -254,7 +254,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) { - match self.fcx.inh.adjustments.borrow_mut().remove(&id) { + let adjustments = self.fcx.inh.tables.borrow_mut().adjustments.remove(&id); + match adjustments { None => { debug!("No adjustments for node {}", id); } @@ -281,7 +282,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } }; debug!("Adjustments for node {}: {:?}", id, resolved_adjustment); - self.tcx().adjustments.borrow_mut().insert( + self.tcx().tables.borrow_mut().adjustments.insert( id, resolved_adjustment); } } @@ -291,7 +292,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { reason: ResolveReason, method_call: MethodCall) { // Resolve any method map entry - match self.fcx.inh.method_map.borrow_mut().remove(&method_call) { + let new_method = match self.fcx.inh.tables.borrow_mut().method_map.remove(&method_call) { Some(method) => { debug!("writeback::resolve_method_map_entry(call={:?}, entry={:?})", method_call, @@ -302,9 +303,17 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { substs: self.resolve(&method.substs, reason), }; - self.tcx().method_map.borrow_mut().insert( + Some(new_method) + } + None => None + }; + + //NB(jroesch): We need to match twice to avoid a double borrow which would cause an ICE + match new_method { + Some(method) => { + self.tcx().tables.borrow_mut().method_map.insert( method_call, - new_method); + method); } None => {} } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 06bd572ac12..5441f0b6772 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -448,7 +448,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)", source, target); - let infcx = new_infer_ctxt(tcx); + let infcx = new_infer_ctxt(tcx, Some(param_env)); let check_mutbl = |mt_a: ty::mt<'tcx>, mt_b: ty::mt<'tcx>, mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| { @@ -540,13 +540,13 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { fulfill_cx.register_predicate_obligation(&infcx, predicate); // Check that all transitive obligations are satisfied. - if let Err(errors) = fulfill_cx.select_all_or_error(&infcx, ¶m_env) { + if let Err(errors) = fulfill_cx.select_all_or_error(&infcx, &infcx.parameter_environment) { traits::report_fulfillment_errors(&infcx, &errors); } // Finally, resolve all regions. let mut free_regions = FreeRegionMap::new(); - free_regions.relate_free_regions_from_predicates(tcx, ¶m_env.caller_bounds); + free_regions.relate_free_regions_from_predicates(tcx, &infcx.parameter_environment.caller_bounds); infcx.resolve_regions_and_report_errors(&free_regions, impl_did.node); if let Some(kind) = kind { @@ -630,7 +630,7 @@ fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, pub fn check_coherence(crate_context: &CrateCtxt) { CoherenceChecker { crate_context: crate_context, - inference_context: new_infer_ctxt(crate_context.tcx), + inference_context: new_infer_ctxt(crate_context.tcx, None), inherent_impls: RefCell::new(FnvHashMap()), }.check(crate_context.tcx.map.krate()); unsafety::check(crate_context.tcx); diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index b4ad55ef2e4..a851bb93e3f 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -133,7 +133,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { impl1_def_id, impl2_def_id); - let infcx = infer::new_infer_ctxt(self.tcx); + let infcx = infer::new_infer_ctxt(self.tcx, None); if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id) { self.report_overlap_error(trait_def_id, impl1_def_id, impl2_def_id); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index e43a3542b6e..3e2a88e1f79 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2204,7 +2204,7 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>( base_type, base_type_free); - let infcx = infer::new_infer_ctxt(tcx); + let infcx = infer::new_infer_ctxt(tcx, None); drop(::require_same_types(tcx, Some(&infcx), false, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index fc825c198e7..5d589d2ec78 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -88,6 +88,7 @@ This API is completely unstable and subject to change. #![feature(slice_extras)] #![feature(staged_api)] #![feature(vec_push_all)] +#![feature(cell_extras)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -162,7 +163,7 @@ fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, assert!(!item_substs.substs.types.needs_infer()); - tcx.item_substs.borrow_mut().insert(node_id, item_substs); + tcx.tables.borrow_mut().item_substs.insert(node_id, item_substs); } } @@ -187,7 +188,7 @@ fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>, { let result = match maybe_infcx { None => { - let infcx = infer::new_infer_ctxt(tcx); + let infcx = infer::new_infer_ctxt(tcx, None); infer::mk_eqty(&infcx, t1_is_expected, infer::Misc(span), t1, t2) } Some(infcx) => { |
