diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index e261c699b6ac6..a68876b5ae9c0 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -113,6 +113,7 @@ pub enum DepNode { SizedConstraint(D), AssociatedItemDefIds(D), InherentImpls(D), + Tables(D), // The set of impls for a given trait. Ultimately, it would be // nice to get more fine-grained here (e.g., to include a @@ -162,6 +163,7 @@ impl DepNode { ItemSignature, AssociatedItemDefIds, InherentImpls, + Tables, TraitImpls, ReprHints, } @@ -230,6 +232,7 @@ impl DepNode { SizedConstraint(ref d) => op(d).map(SizedConstraint), AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds), InherentImpls(ref d) => op(d).map(InherentImpls), + Tables(ref d) => op(d).map(Tables), TraitImpls(ref d) => op(d).map(TraitImpls), TraitItems(ref d) => op(d).map(TraitItems), ReprHints(ref d) => op(d).map(ReprHints), diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index a6ffe7cea5592..bd0ff695d093a 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -23,10 +23,6 @@ pub struct NodeCollector<'ast> { pub(super) map: Vec>, /// The parent of this node pub parent_node: NodeId, - /// If true, completely ignore nested items. We set this when loading - /// HIR from metadata, since in that case we only want the HIR for - /// one specific item (and not the ones nested inside of it). - pub ignore_nested_items: bool } impl<'ast> NodeCollector<'ast> { @@ -35,30 +31,12 @@ impl<'ast> NodeCollector<'ast> { krate: krate, map: vec![], parent_node: CRATE_NODE_ID, - ignore_nested_items: false }; collector.insert_entry(CRATE_NODE_ID, RootCrate); collector } - pub(super) fn extend(krate: &'ast Crate, - parent: &'ast InlinedItem, - parent_node: NodeId, - map: Vec>) - -> NodeCollector<'ast> { - let mut collector = NodeCollector { - krate: krate, - map: map, - parent_node: parent_node, - ignore_nested_items: true - }; - - collector.insert_entry(parent_node, RootInlinedParent(parent)); - - collector - } - fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) { debug!("ast_map: {:?} => {:?}", id, entry); let len = self.map.len(); @@ -92,27 +70,19 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { fn visit_nested_item(&mut self, item: ItemId) { debug!("visit_nested_item: {:?}", item); - if !self.ignore_nested_items { - self.visit_item(self.krate.item(item.id)) - } + self.visit_item(self.krate.item(item.id)); } fn visit_nested_trait_item(&mut self, item_id: TraitItemId) { - if !self.ignore_nested_items { - self.visit_trait_item(self.krate.trait_item(item_id)) - } + self.visit_trait_item(self.krate.trait_item(item_id)); } fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { - if !self.ignore_nested_items { - self.visit_impl_item(self.krate.impl_item(item_id)) - } + self.visit_impl_item(self.krate.impl_item(item_id)); } fn visit_nested_body(&mut self, id: BodyId) { - if !self.ignore_nested_items { - self.visit_body(self.krate.body(id)) - } + self.visit_body(self.krate.body(id)); } fn visit_item(&mut self, i: &'ast Item) { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 27ebeea9ad91d..7c0621279fd6f 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -25,28 +25,18 @@ use syntax::codemap::Spanned; use syntax_pos::Span; use hir::*; -use hir::intravisit::Visitor; use hir::print::Nested; +use util::nodemap::DefIdMap; use arena::TypedArena; use std::cell::RefCell; use std::io; -use std::mem; pub mod blocks; mod collector; mod def_collector; pub mod definitions; -/// The data we save and restore about an inlined item or method. This is not -/// part of the AST that we parse from a file, but it becomes part of the tree -/// that we trans. -#[derive(Debug)] -struct InlinedItem { - def_id: DefId, - body: Body, -} - #[derive(Copy, Clone, Debug)] pub enum Node<'ast> { NodeItem(&'ast Item), @@ -99,7 +89,6 @@ enum MapEntry<'ast> { /// Roots for node trees. RootCrate, - RootInlinedParent(&'ast InlinedItem) } impl<'ast> Clone for MapEntry<'ast> { @@ -152,8 +141,7 @@ impl<'ast> MapEntry<'ast> { EntryVisibility(id, _) => id, NotPresent | - RootCrate | - RootInlinedParent(_) => return None, + RootCrate => return None, }) } @@ -225,7 +213,7 @@ impl<'ast> MapEntry<'ast> { pub struct Forest { krate: Crate, pub dep_graph: DepGraph, - inlined_items: TypedArena + inlined_bodies: TypedArena } impl Forest { @@ -233,7 +221,7 @@ impl Forest { Forest { krate: krate, dep_graph: dep_graph.clone(), - inlined_items: TypedArena::new() + inlined_bodies: TypedArena::new() } } @@ -263,20 +251,15 @@ pub struct Map<'ast> { /// /// Also, indexing is pretty quick when you've got a vector and /// plain old integers. - map: RefCell>>, + map: Vec>, definitions: Definitions, - /// All NodeIds that are numerically greater or equal to this value come - /// from inlined items. - local_node_id_watermark: NodeId, + /// Bodies inlined from other crates are cached here. + inlined_bodies: RefCell>, } impl<'ast> Map<'ast> { - pub fn is_inlined_node_id(&self, id: NodeId) -> bool { - id >= self.local_node_id_watermark - } - /// Registers a read in the dependency graph of the AST node with /// the given `id`. This needs to be called each time a public /// function returns the HIR for a node -- in other words, when it @@ -289,111 +272,71 @@ impl<'ast> Map<'ast> { } fn dep_node(&self, id0: NodeId) -> DepNode { - let map = self.map.borrow(); let mut id = id0; - if !self.is_inlined_node_id(id) { - let mut last_expr = None; - loop { - let entry = map[id.as_usize()]; - match entry { - EntryItem(..) | - EntryTraitItem(..) | - EntryImplItem(..) => { - if let Some(last_id) = last_expr { - // The body may have a separate dep node - if entry.is_body_owner(last_id) { - let def_id = self.local_def_id(id); - return DepNode::HirBody(def_id); - } + let mut last_expr = None; + loop { + let entry = self.map[id.as_usize()]; + match entry { + EntryItem(..) | + EntryTraitItem(..) | + EntryImplItem(..) => { + if let Some(last_id) = last_expr { + // The body may have a separate dep node + if entry.is_body_owner(last_id) { + let def_id = self.local_def_id(id); + return DepNode::HirBody(def_id); } - return DepNode::Hir(self.local_def_id(id)); } + return DepNode::Hir(self.local_def_id(id)); + } - EntryVariant(p, v) => { - id = p; + EntryVariant(p, v) => { + id = p; - if last_expr.is_some() { - if v.node.disr_expr.map(|e| e.node_id) == last_expr { - // The enum parent holds both Hir and HirBody nodes. - let def_id = self.local_def_id(id); - return DepNode::HirBody(def_id); - } + if last_expr.is_some() { + if v.node.disr_expr.map(|e| e.node_id) == last_expr { + // The enum parent holds both Hir and HirBody nodes. + let def_id = self.local_def_id(id); + return DepNode::HirBody(def_id); } } + } - EntryForeignItem(p, _) | - EntryField(p, _) | - EntryStmt(p, _) | - EntryTy(p, _) | - EntryTraitRef(p, _) | - EntryLocal(p, _) | - EntryPat(p, _) | - EntryBlock(p, _) | - EntryStructCtor(p, _) | - EntryLifetime(p, _) | - EntryTyParam(p, _) | - EntryVisibility(p, _) => - id = p, - - EntryExpr(p, _) => { - last_expr = Some(id); - id = p; - } - - RootCrate => { - return DepNode::Hir(DefId::local(CRATE_DEF_INDEX)); - } - - RootInlinedParent(_) => - bug!("node {} has inlined ancestor but is not inlined", id0), - - NotPresent => - // Some nodes, notably macro definitions, are not - // present in the map for whatever reason, but - // they *do* have def-ids. So if we encounter an - // empty hole, check for that case. - return self.opt_local_def_id(id) - .map(|def_id| DepNode::Hir(def_id)) - .unwrap_or_else(|| { - bug!("Walking parents from `{}` \ - led to `NotPresent` at `{}`", - id0, id) - }), + EntryForeignItem(p, _) | + EntryField(p, _) | + EntryStmt(p, _) | + EntryTy(p, _) | + EntryTraitRef(p, _) | + EntryLocal(p, _) | + EntryPat(p, _) | + EntryBlock(p, _) | + EntryStructCtor(p, _) | + EntryLifetime(p, _) | + EntryTyParam(p, _) | + EntryVisibility(p, _) => + id = p, + + EntryExpr(p, _) => { + last_expr = Some(id); + id = p; } - } - } else { - // reading from an inlined def-id is really a read out of - // the metadata from which we loaded the item. - loop { - match map[id.as_usize()] { - EntryItem(p, _) | - EntryForeignItem(p, _) | - EntryTraitItem(p, _) | - EntryImplItem(p, _) | - EntryVariant(p, _) | - EntryField(p, _) | - EntryExpr(p, _) | - EntryStmt(p, _) | - EntryTy(p, _) | - EntryTraitRef(p, _) | - EntryLocal(p, _) | - EntryPat(p, _) | - EntryBlock(p, _) | - EntryStructCtor(p, _) | - EntryLifetime(p, _) | - EntryTyParam(p, _) | - EntryVisibility(p, _) => - id = p, - - RootInlinedParent(parent) => - return DepNode::MetaData(parent.def_id), - - RootCrate => - bug!("node {} has crate ancestor but is inlined", id0), - - NotPresent => - bug!("node {} is inlined but not present in map", id0), + + RootCrate => { + return DepNode::Hir(DefId::local(CRATE_DEF_INDEX)); } + + NotPresent => + // Some nodes, notably macro definitions, are not + // present in the map for whatever reason, but + // they *do* have def-ids. So if we encounter an + // empty hole, check for that case. + return self.opt_local_def_id(id) + .map(|def_id| DepNode::Hir(def_id)) + .unwrap_or_else(|| { + bug!("Walking parents from `{}` \ + led to `NotPresent` at `{}`", + id0, id) + }), } } } @@ -442,11 +385,11 @@ impl<'ast> Map<'ast> { } fn entry_count(&self) -> usize { - self.map.borrow().len() + self.map.len() } fn find_entry(&self, id: NodeId) -> Option> { - self.map.borrow().get(id.as_usize()).cloned() + self.map.get(id.as_usize()).cloned() } pub fn krate(&self) -> &'ast Crate { @@ -483,7 +426,7 @@ impl<'ast> Map<'ast> { /// for embedded constant expressions (e.g. `N` in `[T; N]`). pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId { let parent = self.get_parent_node(node_id); - if self.map.borrow()[parent.as_usize()].is_body_owner(node_id) { + if self.map[parent.as_usize()].is_body_owner(node_id) { parent } else { node_id @@ -644,11 +587,7 @@ impl<'ast> Map<'ast> { } pub fn get_parent_did(&self, id: NodeId) -> DefId { - let parent = self.get_parent(id); - match self.find_entry(parent) { - Some(RootInlinedParent(ii)) => ii.def_id, - _ => self.local_def_id(parent) - } + self.local_def_id(self.get_parent(id)) } pub fn get_foreign_abi(&self, id: NodeId) -> Abi { @@ -660,8 +599,6 @@ impl<'ast> Map<'ast> { _ => None } } - /// Wrong but OK, because the only inlined foreign items are intrinsics. - Some(RootInlinedParent(_)) => Some(Abi::RustIntrinsic), _ => None }; match abi { @@ -737,11 +674,17 @@ impl<'ast> Map<'ast> { } } - pub fn expect_inlined_body(&self, id: NodeId) -> &'ast Body { - match self.find_entry(id) { - Some(RootInlinedParent(inlined_item)) => &inlined_item.body, - _ => bug!("expected inlined item, found {}", self.node_to_string(id)), - } + pub fn get_inlined_body(&self, def_id: DefId) -> Option<&'ast Body> { + self.inlined_bodies.borrow().get(&def_id).map(|&body| { + self.dep_graph.read(DepNode::MetaData(def_id)); + body + }) + } + + pub fn intern_inlined_body(&self, def_id: DefId, body: Body) -> &'ast Body { + let body = self.forest.inlined_bodies.alloc(body); + self.inlined_bodies.borrow_mut().insert(def_id, body); + body } /// Returns the name associated with the given NodeId's AST. @@ -824,7 +767,6 @@ impl<'ast> Map<'ast> { Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v), Some(RootCrate) => self.forest.krate.span, - Some(RootInlinedParent(parent)) => parent.body.value.span, Some(NotPresent) | None => { bug!("hir::map::Map::span: id not in map: {:?}", id) } @@ -973,41 +915,15 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest, entries, vector_length, (entries as f64 / vector_length as f64) * 100.); } - let local_node_id_watermark = NodeId::new(map.len()); - Map { forest: forest, dep_graph: forest.dep_graph.clone(), - map: RefCell::new(map), + map: map, definitions: definitions, - local_node_id_watermark: local_node_id_watermark, + inlined_bodies: RefCell::new(DefIdMap()), } } -/// Used for bodies loaded from external crate that are being inlined into this -/// crate. -pub fn map_decoded_body<'ast>(map: &Map<'ast>, - def_id: DefId, - body: Body, - parent_id: NodeId) - -> &'ast Body { - let _ignore = map.forest.dep_graph.in_ignore(); - - let ii = map.forest.inlined_items.alloc(InlinedItem { - def_id: def_id, - body: body - }); - - let mut collector = NodeCollector::extend(map.krate(), - ii, - parent_id, - mem::replace(&mut *map.map.borrow_mut(), vec![])); - collector.visit_body(&ii.body); - *map.map.borrow_mut() = collector.map; - - &ii.body -} - /// Identical to the `PpAnn` implementation for `hir::Crate`, /// except it avoids creating a dependency on the whole crate. impl<'ast> print::PpAnn for Map<'ast> { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 0860881bf6bd5..3df64ebd1581b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -65,6 +65,7 @@ pub struct GlobalArenas<'tcx> { trait_def: TypedArena, adt_def: TypedArena, mir: TypedArena>>, + tables: TypedArena>, } impl<'tcx> GlobalArenas<'tcx> { @@ -75,6 +76,7 @@ impl<'tcx> GlobalArenas<'tcx> { trait_def: TypedArena::new(), adt_def: TypedArena::new(), mir: TypedArena::new(), + tables: TypedArena::new(), } } } @@ -189,6 +191,7 @@ pub struct CommonTypes<'tcx> { pub err: Ty<'tcx>, } +#[derive(RustcEncodable, RustcDecodable)] pub struct Tables<'tcx> { /// Resolved definitions for `::X` associated paths. pub type_relative_path_defs: NodeMap, @@ -399,7 +402,7 @@ pub struct GlobalCtxt<'tcx> { free_region_maps: RefCell>, // FIXME: jroesch make this a refcell - pub tables: RefCell>, + pub tables: RefCell>>, /// Maps from a trait item to the trait item "descriptor" pub associated_items: RefCell>>, @@ -651,6 +654,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.global_arenas.mir.alloc(RefCell::new(mir)) } + pub fn alloc_tables(self, tables: ty::Tables<'gcx>) -> &'gcx ty::Tables<'gcx> { + self.global_arenas.tables.alloc(tables) + } + pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef { self.global_arenas.trait_def.alloc(def) } @@ -749,7 +756,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { variance_computed: Cell::new(false), sess: s, trait_map: resolutions.trait_map, - tables: RefCell::new(Tables::empty()), + tables: RefCell::new(DepTrackingMap::new(dep_graph.clone())), impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), adt_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index b2337372805a9..59d22d270b15d 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -48,3 +48,4 @@ dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc> } dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell> } dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind } dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> } +dep_map_ty! { Tables: Tables(DefId) -> &'tcx ty::Tables<'tcx> } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 86a9372989dc5..a88b1e3ece964 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -321,7 +321,7 @@ pub struct MethodCallee<'tcx> { /// needed to add to the side tables. Thus to disambiguate /// we also keep track of whether there's an adjustment in /// our key. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct MethodCall { pub expr_id: NodeId, pub autoderef: u32 @@ -501,7 +501,7 @@ impl Slice { /// Upvars do not get their own node-id. Instead, we use the pair of /// the original var id (that is, the root variable that is referenced /// by the upvar) and the id of the closure expression. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct UpvarId { pub var_id: NodeId, pub closure_expr_id: NodeId, @@ -1917,19 +1917,30 @@ impl BorrowKind { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn tables(self) -> Ref<'a, Tables<'gcx>> { - self.tables.borrow() - } - - pub fn body_tables(self, body: hir::BodyId) -> &'a Tables<'gcx> { + pub fn body_tables(self, body: hir::BodyId) -> &'gcx Tables<'gcx> { self.item_tables(self.map.body_owner_def_id(body)) } - pub fn item_tables(self, _def_id: DefId) -> &'a Tables<'gcx> { - // HACK(eddyb) temporarily work around RefCell until proper per-body tables - unsafe { - mem::transmute::<&Tables, &Tables>(&self.tables()) - } + pub fn item_tables(self, def_id: DefId) -> &'gcx Tables<'gcx> { + self.tables.memoize(def_id, || { + if def_id.is_local() { + // Closures' tables come from their outermost function, + // as they are part of the same "inference environment". + let outer_def_id = self.closure_base_def_id(def_id); + if outer_def_id != def_id { + return self.item_tables(outer_def_id); + } + + bug!("No def'n found for {:?} in tcx.tables", def_id); + } + + // Cross-crate side-tables only exist alongside serialized HIR. + self.sess.cstore.maybe_get_item_body(self.global_tcx(), def_id).map(|_| { + self.tables.borrow()[&def_id] + }).unwrap_or_else(|| { + bug!("tcx.item_tables({:?}): missing from metadata", def_id) + }) + }) } pub fn expr_span(self, id: NodeId) -> Span { diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 442d583907b1f..bc72c8fb9b6fe 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -52,21 +52,20 @@ macro_rules! math { fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, variant_def: DefId) - -> Option<(&'tcx Expr, &'a ty::Tables<'tcx>)> { + -> Option<(&'tcx Expr, Option<&'a ty::Tables<'tcx>>)> { if let Some(variant_node_id) = tcx.map.as_local_node_id(variant_def) { let enum_node_id = tcx.map.get_parent(variant_node_id); if let Some(ast_map::NodeItem(it)) = tcx.map.find(enum_node_id) { - match it.node { - hir::ItemEnum(hir::EnumDef { ref variants }, _) => { - for variant in variants { - if variant.node.data.id() == variant_node_id { - return variant.node.disr_expr.map(|e| { - (&tcx.map.body(e).value, tcx.body_tables(e)) - }); - } + if let hir::ItemEnum(ref edef, _) = it.node { + for variant in &edef.variants { + if variant.node.data.id() == variant_node_id { + return variant.node.disr_expr.map(|e| { + let def_id = tcx.map.body_owner_def_id(e); + (&tcx.map.body(e).value, + tcx.tables.borrow().get(&def_id).cloned()) + }); } } - _ => {} } } } @@ -81,7 +80,8 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>) - -> Option<(&'tcx Expr, &'a ty::Tables<'tcx>, + -> Option<(&'tcx Expr, + Option<&'a ty::Tables<'tcx>>, Option>)> { if let Some(node_id) = tcx.map.as_local_node_id(def_id) { match tcx.map.find(node_id) { @@ -92,7 +92,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Some(ast_map::NodeImplItem(&hir::ImplItem { node: hir::ImplItemKind::Const(ref ty, body), .. })) => { - Some((&tcx.map.body(body).value, tcx.item_tables(def_id), + Some((&tcx.map.body(body).value, + tcx.tables.borrow().get(&def_id).cloned(), tcx.ast_ty_to_prim_ty(ty))) } Some(ast_map::NodeTraitItem(ti)) => match ti.node { @@ -104,7 +105,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_id = tcx.map.get_parent(node_id); let trait_id = tcx.map.local_def_id(trait_id); let default_value = default.map(|body| { - (&tcx.map.body(body).value, tcx.item_tables(def_id), + (&tcx.map.body(body).value, + tcx.tables.borrow().get(&def_id).cloned(), tcx.ast_ty_to_prim_ty(ty)) }); resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs) @@ -124,7 +126,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } else { let expr_tables_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { - (&body.value, tcx.item_tables(def_id), + (&body.value, Some(tcx.item_tables(def_id)), Some(tcx.sess.cstore.item_type(tcx, def_id))) }); match tcx.sess.cstore.describe_def(def_id) { @@ -152,12 +154,13 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option<(&'tcx hir::Body, &'a ty::Tables<'tcx>)> + -> Option<(&'tcx hir::Body, Option<&'a ty::Tables<'tcx>>)> { if let Some(node_id) = tcx.map.as_local_node_id(def_id) { FnLikeNode::from_node(tcx.map.get(node_id)).and_then(|fn_like| { if fn_like.constness() == hir::Constness::Const { - Some((tcx.map.body(fn_like.body()), tcx.body_tables(fn_like.body()))) + Some((tcx.map.body(fn_like.body()), + tcx.tables.borrow().get(&def_id).cloned())) } else { None } @@ -165,7 +168,7 @@ fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) } else { if tcx.sess.cstore.is_const_fn(def_id) { tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { - (body, tcx.item_tables(def_id)) + (body, Some(tcx.item_tables(def_id))) }) } else { None @@ -223,19 +226,24 @@ pub fn note_const_eval_err<'a, 'tcx>( pub struct ConstContext<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - tables: &'a ty::Tables<'tcx>, + tables: Option<&'a ty::Tables<'tcx>>, fn_args: Option> } impl<'a, 'tcx> ConstContext<'a, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self { - ConstContext::with_tables(tcx, tcx.body_tables(body)) + let def_id = tcx.map.body_owner_def_id(body); + ConstContext { + tcx: tcx, + tables: tcx.tables.borrow().get(&def_id).cloned(), + fn_args: None + } } pub fn with_tables(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::Tables<'tcx>) -> Self { ConstContext { tcx: tcx, - tables: tables, + tables: Some(tables), fn_args: None } } @@ -436,7 +444,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, let ety = match ty_hint { ExprTypeChecked => { // After type-checking, expr_ty is guaranteed to succeed. - Some(cx.tables.expr_ty(e)) + cx.tables.map(|tables| tables.expr_ty(e)) } UncheckedExprHint(ty) => { // Use the type hint; it's not guaranteed to be right, but it's @@ -447,7 +455,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, // This expression might not be type-checked, and we have no hint. // Try to query the context for a type anyway; we might get lucky // (for example, if the expression was imported from another crate). - cx.tables.expr_ty_opt(e) + cx.tables.and_then(|tables| tables.expr_ty_opt(e)) } }; let result = match e.node { @@ -594,7 +602,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, let base_hint = if let ExprTypeChecked = ty_hint { ExprTypeChecked } else { - match cx.tables.expr_ty_opt(&base) { + match cx.tables.and_then(|tables| tables.expr_ty_opt(&base)) { Some(t) => UncheckedExprHint(t), None => ty_hint } @@ -623,12 +631,18 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, } } hir::ExprPath(ref qpath) => { - let def = cx.tables.qpath_def(qpath, e.id); + let def = cx.tables.map(|tables| tables.qpath_def(qpath, e.id)).unwrap_or_else(|| { + // There are no tables so we can only handle already-resolved HIR. + match *qpath { + hir::QPath::Resolved(_, ref path) => path.def, + hir::QPath::TypeRelative(..) => Def::Err + } + }); match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { let substs = if let ExprTypeChecked = ty_hint { - Some(cx.tables.node_id_item_substs(e.id) + Some(cx.tables.and_then(|tables| tables.node_id_item_substs(e.id)) .unwrap_or_else(|| tcx.intern_substs(&[]))) } else { None @@ -638,7 +652,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, Some(ty) => ty_hint.checked_or(ty), None => ty_hint, }; - let cx = ConstContext::with_tables(tcx, tables); + let cx = ConstContext { tcx: tcx, tables: tables, fn_args: None }; match cx.eval(expr, item_hint) { Ok(val) => val, Err(err) => { @@ -652,7 +666,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, }, Def::VariantCtor(variant_def, ..) => { if let Some((expr, tables)) = lookup_variant_by_id(tcx, variant_def) { - let cx = ConstContext::with_tables(tcx, tables); + let cx = ConstContext { tcx: tcx, tables: tables, fn_args: None }; match cx.eval(expr, ty_hint) { Ok(val) => val, Err(err) => { @@ -903,10 +917,10 @@ fn infer<'a, 'tcx>(i: ConstInt, fn resolve_trait_associated_const<'a, 'tcx: 'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: DefId, - default_value: Option<(&'tcx Expr, &'a ty::Tables<'tcx>, Option>)>, + default_value: Option<(&'tcx Expr, Option<&'a ty::Tables<'tcx>>, Option>)>, trait_id: DefId, rcvr_substs: &'tcx Substs<'tcx> -) -> Option<(&'tcx Expr, &'a ty::Tables<'tcx>, Option>)> +) -> Option<(&'tcx Expr, Option<&'a ty::Tables<'tcx>>, Option>)> { let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, rcvr_substs)); debug!("resolve_trait_associated_const: trait_ref={:?}", diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index 86c11dc32da12..fbd15b6eb1035 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -582,7 +582,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { Some((const_expr, const_tables, _const_ty)) => { // Enter the inlined constant's tables temporarily. let old_tables = self.tables; - self.tables = const_tables; + self.tables = const_tables.expect("missing tables after typeck"); let pat = self.lower_const_expr(const_expr, pat_id, span); self.tables = old_tables; return pat; diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 692e1e62c61a6..3c14d38cc3821 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -8,60 +8,31 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::hir::map as ast_map; +use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; -use rustc::hir::intravisit::{Visitor, IdRangeComputingVisitor, IdRange, NestedVisitorMap}; - -use cstore::CrateMetadata; use encoder::EncodeContext; use schema::*; use rustc::hir; -use rustc::hir::def::Def; -use rustc::hir::def_id::DefId; -use rustc::ty::{self, TyCtxt, Ty}; - -use syntax::ast; +use rustc::ty; use rustc_serialize::Encodable; #[derive(RustcEncodable, RustcDecodable)] pub struct Ast<'tcx> { - id_range: IdRange, - body: Lazy, - side_tables: LazySeq<(ast::NodeId, TableEntry<'tcx>)>, + pub body: Lazy, + pub tables: Lazy>, pub nested_bodies: LazySeq, pub rvalue_promotable_to_static: bool, } -#[derive(RustcEncodable, RustcDecodable)] -enum TableEntry<'tcx> { - TypeRelativeDef(Def), - NodeType(Ty<'tcx>), - ItemSubsts(ty::ItemSubsts<'tcx>), - Adjustment(ty::adjustment::Adjustment<'tcx>), -} - impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - pub fn encode_body(&mut self, body: hir::BodyId) -> Lazy> { - let body = self.tcx.map.body(body); - - let mut id_visitor = IdRangeComputingVisitor::new(&self.tcx.map); - id_visitor.visit_body(body); + pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy> { + let body = self.tcx.map.body(body_id); + let lazy_body = self.lazy(body); - let body_pos = self.position(); - body.encode(self).unwrap(); - - let tables_pos = self.position(); - let tables_count = { - let mut visitor = SideTableEncodingIdVisitor { - tables: self.tcx.body_tables(body.id()), - ecx: self, - count: 0, - }; - visitor.visit_body(body); - visitor.count - }; + let tables = self.tcx.body_tables(body_id); + let lazy_tables = self.lazy(tables); let nested_pos = self.position(); let nested_count = { @@ -77,45 +48,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id]; self.lazy(&Ast { - id_range: id_visitor.result(), - body: Lazy::with_position(body_pos), - side_tables: LazySeq::with_position_and_length(tables_pos, tables_count), + body: lazy_body, + tables: lazy_tables, nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count), rvalue_promotable_to_static: rvalue_promotable_to_static }) } } -struct SideTableEncodingIdVisitor<'a, 'b: 'a, 'tcx: 'b> { - ecx: &'a mut EncodeContext<'b, 'tcx>, - tables: &'a ty::Tables<'tcx>, - count: usize, -} - -impl<'a, 'b, 'tcx> Visitor<'tcx> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.ecx.tcx.map) - } - - fn visit_id(&mut self, id: ast::NodeId) { - debug!("Encoding side tables for id {}", id); - - let tables = self.tables; - let mut encode = |entry: Option| { - if let Some(entry) = entry { - (id, entry).encode(self.ecx).unwrap(); - self.count += 1; - } - }; - - encode(tables.type_relative_path_defs.get(&id).cloned() - .map(TableEntry::TypeRelativeDef)); - encode(tables.node_types.get(&id).cloned().map(TableEntry::NodeType)); - encode(tables.item_substs.get(&id).cloned().map(TableEntry::ItemSubsts)); - encode(tables.adjustments.get(&id).cloned().map(TableEntry::Adjustment)); - } -} - struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> { ecx: &'a mut EncodeContext<'b, 'tcx>, count: usize, @@ -134,41 +74,3 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedBodyEncodingVisitor<'a, 'b, 'tcx> { self.visit_body(body); } } - -/// Decodes an item's body from its AST in the cdata's metadata and adds it to the -/// ast-map. -pub fn decode_body<'a, 'tcx>(cdata: &CrateMetadata, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId, - ast: Ast<'tcx>) - -> &'tcx hir::Body { - debug!("> Decoding inlined fn: {}", tcx.item_path_str(def_id)); - - let cnt = ast.id_range.max.as_usize() - ast.id_range.min.as_usize(); - let start = tcx.sess.reserve_node_ids(cnt); - let id_ranges = [ast.id_range, - IdRange { - min: start, - max: ast::NodeId::new(start.as_usize() + cnt), - }]; - - for (id, entry) in ast.side_tables.decode((cdata, tcx, id_ranges)) { - match entry { - TableEntry::TypeRelativeDef(def) => { - tcx.tables.borrow_mut().type_relative_path_defs.insert(id, def); - } - TableEntry::NodeType(ty) => { - tcx.tables.borrow_mut().node_types.insert(id, ty); - } - TableEntry::ItemSubsts(item_substs) => { - tcx.tables.borrow_mut().item_substs.insert(id, item_substs); - } - TableEntry::Adjustment(adj) => { - tcx.tables.borrow_mut().adjustments.insert(id, adj); - } - } - } - - let body = ast.body.decode((cdata, tcx, id_ranges)); - ast_map::map_decoded_body(&tcx.map, def_id, body, tcx.sess.next_node_id()) -} diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index aab4034b7705a..efc19abb33e1b 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -97,7 +97,6 @@ pub struct CStore { used_link_args: RefCell>, statically_included_foreign_items: RefCell>, pub dllimport_foreign_items: RefCell>, - pub inlined_item_cache: RefCell>>, pub visible_parent_map: RefCell>, } @@ -112,7 +111,6 @@ impl CStore { statically_included_foreign_items: RefCell::new(FxHashSet()), dllimport_foreign_items: RefCell::new(FxHashSet()), visible_parent_map: RefCell::new(FxHashMap()), - inlined_item_cache: RefCell::new(FxHashMap()), } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 64513fa41b219..3d025e984b040 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -434,27 +434,14 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { def_id: DefId) -> Option<&'tcx hir::Body> { - self.dep_graph.read(DepNode::MetaData(def_id)); - - if let Some(&cached) = self.inlined_item_cache.borrow().get(&def_id) { - return cached.map(|root_id| { - // Already inline - debug!("maybe_get_item_body({}): already inline", tcx.item_path_str(def_id)); - tcx.map.expect_inlined_body(root_id) - }); + if let Some(cached) = tcx.map.get_inlined_body(def_id) { + return Some(cached); } + self.dep_graph.read(DepNode::MetaData(def_id)); debug!("maybe_get_item_body({}): inlining item", tcx.item_path_str(def_id)); - let inlined = self.get_crate_data(def_id.krate).maybe_get_item_body(tcx, def_id.index); - - self.inlined_item_cache.borrow_mut().insert(def_id, inlined.map(|body| { - let root_id = tcx.map.get_parent_node(body.value.id); - assert_eq!(tcx.map.get_parent_node(root_id), root_id); - root_id - })); - - inlined + self.get_crate_data(def_id.krate).maybe_get_item_body(tcx, def_id.index) } fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index dad956afb5e60..f3a673898b25c 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -10,13 +10,11 @@ // Decoding metadata from a single crate's metadata -use astencode::decode_body; use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary}; use schema::*; use rustc::hir::map::{DefKey, DefPath, DefPathData}; use rustc::hir; -use rustc::hir::intravisit::IdRange; use rustc::middle::cstore::LinkagePreference; use rustc::hir::def::{self, Def, CtorKind}; @@ -40,7 +38,7 @@ use std::u32; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; -use syntax::ast::{self, NodeId}; +use syntax::ast; use syntax::codemap; use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP}; use rustc_i128::{u128, i128}; @@ -50,8 +48,6 @@ pub struct DecodeContext<'a, 'tcx: 'a> { cdata: Option<&'a CrateMetadata>, sess: Option<&'a Session>, tcx: Option>, - from_id_range: IdRange, - to_id_range: IdRange, // Cache the last used filemap for translating spans as an optimization. last_filemap_index: usize, @@ -67,18 +63,12 @@ pub trait Metadata<'a, 'tcx>: Copy { fn tcx(self) -> Option> { None } fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { - let id_range = IdRange { - min: NodeId::from_u32(u32::MIN), - max: NodeId::from_u32(u32::MAX), - }; let tcx = self.tcx(); DecodeContext { opaque: opaque::Decoder::new(self.raw_bytes(), pos), cdata: self.cdata(), sess: self.sess().or(tcx.map(|tcx| tcx.sess)), tcx: tcx, - from_id_range: id_range, - to_id_range: id_range, last_filemap_index: 0, lazy_state: LazyState::NoNode, } @@ -128,26 +118,6 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx> } } -// HACK(eddyb) Only used by astencode to customize the from/to IdRange's. -impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>, [IdRange; 2]) { - fn raw_bytes(self) -> &'a [u8] { - self.0.raw_bytes() - } - fn cdata(self) -> Option<&'a CrateMetadata> { - Some(self.0) - } - fn tcx(self) -> Option> { - Some(self.1) - } - - fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { - let mut dcx = (self.0, self.1).decoder(pos); - dcx.from_id_range = self.2[0]; - dcx.to_id_range = self.2[1]; - dcx - } -} - impl<'a, 'tcx: 'a, T: Decodable> Lazy { pub fn decode>(self, meta: M) -> T { let mut dcx = meta.decoder(self.position); @@ -256,28 +226,6 @@ impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { } } -impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { - fn specialized_decode(&mut self) -> Result { - let id = u32::decode(self)?; - - // from_id_range should be non-empty - assert!(!self.from_id_range.empty()); - // Make sure that translating the NodeId will actually yield a - // meaningful result - if !self.from_id_range.contains(NodeId::from_u32(id)) { - bug!("NodeId::decode: {} out of DecodeContext range ({:?} -> {:?})", - id, - self.from_id_range, - self.to_id_range); - } - - // Use wrapping arithmetic because otherwise it introduces control flow. - // Maybe we should just have the control flow? -- aatch - Ok(NodeId::from_u32(id.wrapping_sub(self.from_id_range.min.as_u32()) - .wrapping_add(self.to_id_range.min.as_u32()))) - } -} - impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { let cnum = CrateNum::from_u32(u32::decode(self)?); @@ -829,7 +777,14 @@ impl<'a, 'tcx> CrateMetadata { -> Option<&'tcx hir::Body> { if self.is_proc_macro(id) { return None; } self.entry(id).ast.map(|ast| { - decode_body(self, tcx, self.local_def_id(id), ast.decode(self)) + let def_id = self.local_def_id(id); + let ast = ast.decode(self); + + let tables = ast.tables.decode((self, tcx)); + tcx.tables.borrow_mut().insert(def_id, tcx.alloc_tables(tables)); + + let body = ast.body.decode((self, tcx)); + tcx.map.intern_inlined_body(def_id, body) }) } diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index aa5ebdf77a2ab..4b553a71b8325 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -20,7 +20,6 @@ use rustc::mir::transform::MirSource; use rustc::middle::const_val::ConstVal; use rustc_const_eval::{ConstContext, EvalHint, fatal_const_eval_err}; use rustc_data_structures::indexed_vec::Idx; -use rustc::dep_graph::DepNode; use rustc::hir::def_id::DefId; use rustc::hir::map::blocks::FnLikeNode; use rustc::infer::InferCtxt; @@ -52,17 +51,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { MirSource::Promoted(..) => bug!(), }; - let src_node_id = src.item_id(); - - // We are going to be accessing various tables - // generated by TypeckItemBody; we also assume - // that the body passes type check. These tables - // are not individually tracked, so just register - // a read here. - let src_def_id = infcx.tcx.map.local_def_id(src_node_id); - infcx.tcx.dep_graph.read(DepNode::TypeckItemBody(src_def_id)); - - let attrs = infcx.tcx.map.attrs(src_node_id); + let attrs = infcx.tcx.map.attrs(src.item_id()); // Some functions always have overflow checks enabled, // however, they may not get codegen'd, depending on diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 2e2644d91bb6c..a9c1edfdc66cc 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -95,8 +95,6 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { let sym = ccx.symbol_map() .get(TransItem::Static(id)) .expect("Local statics should always be in the SymbolMap"); - // Make sure that this is never executed for something inlined. - assert!(!ccx.tcx().map.is_inlined_node_id(id)); let defined_in_current_codegen_unit = ccx.codegen_unit() .items() diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index f6428465eda20..1473e55b2643c 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1738,14 +1738,6 @@ pub fn create_global_var_metadata(cx: &CrateContext, let tcx = cx.tcx(); - // Don't create debuginfo for globals inlined from other crates. The other - // crate should already contain debuginfo for it. More importantly, the - // global might not even exist in un-inlined form anywhere which would lead - // to a linker errors. - if tcx.map.is_inlined_node_id(node_id) { - return; - } - let node_def_id = tcx.map.local_def_id(node_id); let (var_scope, span) = get_namespace_and_span_for_item(cx, node_def_id); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e7657fb16463c..9e56bcc458d86 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -679,7 +679,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fcx.select_all_obligations_or_error(); // Casts can introduce new obligations. fcx.regionck_fn(fn_id, body); - fcx.resolve_type_vars_in_body(body, fn_id); + fcx.resolve_type_vars_in_body(body); }); } @@ -1246,7 +1246,7 @@ fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, fcx.select_all_obligations_or_error(); fcx.regionck_expr(body); - fcx.resolve_type_vars_in_body(body, id); + fcx.resolve_type_vars_in_body(body); }); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 0f5f8d889e810..02ac7c196b5cb 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -33,10 +33,12 @@ use rustc::hir; // Entry point impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { - pub fn resolve_type_vars_in_body(&self, - body: &'gcx hir::Body, - item_id: ast::NodeId) { + pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) { assert_eq!(self.writeback_errors.get(), false); + + let item_id = self.tcx.map.body_owner(body.id()); + let item_def_id = self.tcx.map.local_def_id(item_id); + let mut wbcx = WritebackCx::new(self); for arg in &body.arguments { wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id); @@ -49,6 +51,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_anon_types(); wbcx.visit_deferred_obligations(item_id); wbcx.visit_type_nodes(); + + let tables = self.tcx.alloc_tables(wbcx.tables); + self.tcx.tables.borrow_mut().insert(item_def_id, tables); } } @@ -63,6 +68,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, + tables: ty::Tables<'gcx>, + // Mapping from free regions of the function to the // early-bound versions of them, visible from the // outside of the function. This is needed by, and @@ -74,6 +81,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>) -> WritebackCx<'cx, 'gcx, 'tcx> { let mut wbcx = WritebackCx { fcx: fcx, + tables: ty::Tables::empty(), free_to_bound_regions: DefIdMap() }; @@ -113,10 +121,10 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { self.fcx.tcx } - fn write_ty_to_tcx(&self, node_id: ast::NodeId, ty: Ty<'gcx>) { - debug!("write_ty_to_tcx({}, {:?})", node_id, ty); + fn write_ty_to_tables(&mut self, node_id: ast::NodeId, ty: Ty<'gcx>) { + debug!("write_ty_to_tables({}, {:?})", node_id, ty); assert!(!ty.needs_infer()); - self.tcx().tables.borrow_mut().node_types.insert(node_id, ty); + self.tables.node_types.insert(node_id, ty); } // Hacky hack: During type-checking, we treat *all* operators @@ -238,13 +246,13 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { let var_ty = self.fcx.local_ty(l.span, l.id); let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span)); - self.write_ty_to_tcx(l.id, var_ty); + self.write_ty_to_tables(l.id, var_ty); intravisit::walk_local(self, l); } } impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { - fn visit_upvar_borrow_map(&self) { + fn visit_upvar_borrow_map(&mut self) { if self.fcx.writeback_errors.get() { return; } @@ -262,11 +270,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { debug!("Upvar capture for {:?} resolved to {:?}", upvar_id, new_upvar_capture); - self.tcx() - .tables - .borrow_mut() - .upvar_capture_map - .insert(*upvar_id, new_upvar_capture); + self.tables.upvar_capture_map.insert(*upvar_id, new_upvar_capture); } } @@ -336,10 +340,10 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } - fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) { + fn visit_node_id(&mut self, reason: ResolveReason, id: ast::NodeId) { // Export associated path extensions. if let Some(def) = self.fcx.tables.borrow_mut().type_relative_path_defs.remove(&id) { - self.tcx().tables.borrow_mut().type_relative_path_defs.insert(id, def); + self.tables.type_relative_path_defs.insert(id, def); } // Resolve any borrowings for the node with id `id` @@ -348,7 +352,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { // Resolve the type of the node with id `id` let n_ty = self.fcx.node_ty(id); let n_ty = self.resolve(&n_ty, reason); - self.write_ty_to_tcx(id, n_ty); + self.write_ty_to_tables(id, n_ty); debug!("Node {} has type {:?}", id, n_ty); // Resolve any substitutions @@ -357,12 +361,12 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { if !item_substs.is_noop() { debug!("write_substs_to_tcx({}, {:?})", id, item_substs); assert!(!item_substs.substs.needs_infer()); - self.tcx().tables.borrow_mut().item_substs.insert(id, item_substs); + self.tables.item_substs.insert(id, item_substs); } }); } - fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) { + fn visit_adjustments(&mut self, reason: ResolveReason, id: ast::NodeId) { let adjustments = self.fcx.tables.borrow_mut().adjustments.remove(&id); match adjustments { None => { @@ -405,13 +409,12 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { target: self.resolve(&adjustment.target, reason) }; debug!("Adjustments for node {}: {:?}", id, resolved_adjustment); - self.tcx().tables.borrow_mut().adjustments.insert( - id, resolved_adjustment); + self.tables.adjustments.insert(id, resolved_adjustment); } } } - fn visit_method_map_entry(&self, + fn visit_method_map_entry(&mut self, reason: ResolveReason, method_call: MethodCall) { // Resolve any method map entry @@ -433,25 +436,25 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { //NB(jroesch): We need to match twice to avoid a double borrow which would cause an ICE if let Some(method) = new_method { - self.tcx().tables.borrow_mut().method_map.insert(method_call, method); + self.tables.method_map.insert(method_call, method); } } - fn visit_liberated_fn_sigs(&self) { + fn visit_liberated_fn_sigs(&mut self) { for (&node_id, fn_sig) in self.fcx.tables.borrow().liberated_fn_sigs.iter() { let fn_sig = self.resolve(fn_sig, ResolvingFnSig(node_id)); - self.tcx().tables.borrow_mut().liberated_fn_sigs.insert(node_id, fn_sig.clone()); + self.tables.liberated_fn_sigs.insert(node_id, fn_sig.clone()); } } - fn visit_fru_field_types(&self) { + fn visit_fru_field_types(&mut self) { for (&node_id, ftys) in self.fcx.tables.borrow().fru_field_types.iter() { let ftys = self.resolve(ftys, ResolvingFieldTypes(node_id)); - self.tcx().tables.borrow_mut().fru_field_types.insert(node_id, ftys); + self.tables.fru_field_types.insert(node_id, ftys); } } - fn visit_deferred_obligations(&self, item_id: ast::NodeId) { + fn visit_deferred_obligations(&mut self, item_id: ast::NodeId) { let deferred_obligations = self.fcx.deferred_obligations.borrow(); let obligations: Vec<_> = deferred_obligations.iter().map(|obligation| { let reason = ResolvingDeferredObligation(obligation.cause.span);