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.
This commit is contained in:
Jared Roesch 2015-06-24 13:40:54 -07:00
parent 2ba46f8bbc
commit 79d02895ff
45 changed files with 427 additions and 252 deletions

View file

@ -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)]

View file

@ -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 => {

View file

@ -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)
}
}

View file

@ -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
};

View file

@ -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>,

View file

@ -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, &param_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) {

View file

@ -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) => {

View file

@ -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) {

View file

@ -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

View file

@ -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())
}
}

View file

@ -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 {

View file

@ -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)

View file

@ -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) {

View file

@ -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) => {

View file

@ -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>,

View file

@ -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 {

View file

@ -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| {