]> git.lizzy.rs Git - rust.git/commitdiff
rustc: store ty::Tables separately for each body (except closures').
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Wed, 4 Jan 2017 02:01:58 +0000 (04:01 +0200)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Fri, 6 Jan 2017 20:23:29 +0000 (22:23 +0200)
17 files changed:
src/librustc/dep_graph/dep_node.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/mod.rs
src/librustc/ty/context.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc_const_eval/eval.rs
src/librustc_const_eval/pattern.rs
src/librustc_metadata/astencode.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_trans/consts.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/writeback.rs

index e261c699b6ac60a03a16d5a340f1cef80a3491bc..a68876b5ae9c0b6bdbe03bc862f5727317c75b14 100644 (file)
@@ -113,6 +113,7 @@ pub enum DepNode<D: Clone + Debug> {
     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 @@ macro_rules! check {
             ItemSignature,
             AssociatedItemDefIds,
             InherentImpls,
+            Tables,
             TraitImpls,
             ReprHints,
         }
@@ -230,6 +232,7 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             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),
index a6ffe7cea5592e752ce7b66b09a8c6e80b700c08..bd0ff695d093a518ca58c395b59953f5cf477fc0 100644 (file)
@@ -23,10 +23,6 @@ pub struct NodeCollector<'ast> {
     pub(super) map: Vec<MapEntry<'ast>>,
     /// 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 @@ pub fn root(krate: &'ast Crate) -> 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<MapEntry<'ast>>)
-                         -> 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 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, '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) {
index 27ebeea9ad91db21f18d477684a6288f5a699365..7c0621279fd6f607f26e0675ec4484c8886db298 100644 (file)
 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 @@ fn parent_node(self) -> Option<NodeId> {
             EntryVisibility(id, _) => id,
 
             NotPresent |
-            RootCrate |
-            RootInlinedParent(_) => return None,
+            RootCrate => return None,
         })
     }
 
@@ -225,7 +213,7 @@ fn is_body_owner(self, node_id: NodeId) -> bool {
 pub struct Forest {
     krate: Crate,
     pub dep_graph: DepGraph,
-    inlined_items: TypedArena<InlinedItem>
+    inlined_bodies: TypedArena<Body>
 }
 
 impl Forest {
@@ -233,7 +221,7 @@ pub fn new(krate: Crate, dep_graph: &DepGraph) -> 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<Vec<MapEntry<'ast>>>,
+    map: Vec<MapEntry<'ast>>,
 
     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<DefIdMap<&'ast Body>>,
 }
 
 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 @@ pub fn read(&self, id: NodeId) {
     }
 
     fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
-        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 @@ pub fn as_local_node_id(&self, def_id: DefId) -> Option<NodeId> {
     }
 
     fn entry_count(&self) -> usize {
-        self.map.borrow().len()
+        self.map.len()
     }
 
     fn find_entry(&self, id: NodeId) -> Option<MapEntry<'ast>> {
-        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 @@ pub fn body(&self, id: BodyId) -> &'ast Body {
     /// 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 @@ pub fn get_enclosing_scope(&self, id: NodeId) -> Option<NodeId> {
     }
 
     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 @@ pub fn get_foreign_abi(&self, id: NodeId) -> Abi {
                     _ => None
                 }
             }
-            /// Wrong but OK, because the only inlined foreign items are intrinsics.
-            Some(RootInlinedParent(_)) => Some(Abi::RustIntrinsic),
             _ => None
         };
         match abi {
@@ -737,11 +674,17 @@ pub fn expect_expr(&self, id: NodeId) -> &'ast Expr {
         }
     }
 
-    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 @@ pub fn span(&self, id: NodeId) -> Span {
             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> {
index 0860881bf6bd52b7d51040ca68569157983a67b0..3df64ebd1581b66237b088c3d5d7d30f473e531f 100644 (file)
@@ -65,6 +65,7 @@ pub struct GlobalArenas<'tcx> {
     trait_def: TypedArena<ty::TraitDef>,
     adt_def: TypedArena<ty::AdtDef>,
     mir: TypedArena<RefCell<Mir<'tcx>>>,
+    tables: TypedArena<ty::Tables<'tcx>>,
 }
 
 impl<'tcx> GlobalArenas<'tcx> {
@@ -75,6 +76,7 @@ pub fn new() -> 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 `<T>::X` associated paths.
     pub type_relative_path_defs: NodeMap<Def>,
@@ -399,7 +402,7 @@ pub struct GlobalCtxt<'tcx> {
     free_region_maps: RefCell<NodeMap<FreeRegionMap>>,
     // FIXME: jroesch make this a refcell
 
-    pub tables: RefCell<Tables<'tcx>>,
+    pub tables: RefCell<DepTrackingMap<maps::Tables<'tcx>>>,
 
     /// Maps from a trait item to the trait item "descriptor"
     pub associated_items: RefCell<DepTrackingMap<maps::AssociatedItems<'tcx>>>,
@@ -651,6 +654,10 @@ pub fn alloc_mir(self, mir: Mir<'gcx>) -> &'gcx RefCell<Mir<'gcx>> {
         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 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             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())),
index b2337372805a92f13fcb9e182e8b948eee0267d4..59d22d270b15d49f946af7ec5b272586d8078ea4 100644 (file)
@@ -48,3 +48,4 @@ fn to_dep_node(key: &$key) -> DepNode<DefId> { DepNode::$node_name(*key) }
 dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>> }
 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> }
index 86a9372989dc5ed90288812c2e6c2cf0439dcca1..a88b1e3ece9641b1ffdc80bf44ad9edb0b780246 100644 (file)
@@ -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 @@ pub fn empty<'a>() -> &'a Slice<T> {
 /// 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 @@ pub fn to_user_str(&self) -> &'static str {
 }
 
 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 {
index 442d583907b1f069c2351baf3b59c82997acaf82..bc72c8fb9b6fe14eb2cb71b9041a71be6fdc4500 100644 (file)
@@ -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<ty::Ty<'tcx>>)> {
     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<DefIdMap<ConstVal>>
 }
 
 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<ty::Ty<'tcx>>)>,
+    default_value: Option<(&'tcx Expr, Option<&'a ty::Tables<'tcx>>, Option<ty::Ty<'tcx>>)>,
     trait_id: DefId,
     rcvr_substs: &'tcx Substs<'tcx>
-) -> Option<(&'tcx Expr, &'a ty::Tables<'tcx>, Option<ty::Ty<'tcx>>)>
+) -> Option<(&'tcx Expr, Option<&'a ty::Tables<'tcx>>, Option<ty::Ty<'tcx>>)>
 {
     let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, rcvr_substs));
     debug!("resolve_trait_associated_const: trait_ref={:?}",
index 86c11dc32da12570bbd6934e2726baf48808692d..fbd15b6eb103531fbd6e746ddd7c31c9de95b869 100644 (file)
@@ -582,7 +582,7 @@ fn lower_path(&mut self,
                     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;
index 692e1e62c61a6f2339b599a3203a01761ab104fc..3c14d38cc38211a6ad32612476a1d54ef28648c8 100644 (file)
@@ -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<hir::Body>,
-    side_tables: LazySeq<(ast::NodeId, TableEntry<'tcx>)>,
+    pub body: Lazy<hir::Body>,
+    pub tables: Lazy<ty::Tables<'tcx>>,
     pub nested_bodies: LazySeq<hir::Body>,
     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<Ast<'tcx>> {
-        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<Ast<'tcx>> {
+        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 @@ pub fn encode_body(&mut self, body: hir::BodyId) -> Lazy<Ast<'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<TableEntry>| {
-            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 @@ fn visit_nested_body(&mut self, body: hir::BodyId) {
         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())
-}
index aab4034b7705aee99a5747a42d74bcc44a8e4e15..efc19abb33e1b5fdb34928a940b18eff6897c471 100644 (file)
@@ -97,7 +97,6 @@ pub struct CStore {
     used_link_args: RefCell<Vec<String>>,
     statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
     pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>,
-    pub inlined_item_cache: RefCell<DefIdMap<Option<ast::NodeId>>>,
     pub visible_parent_map: RefCell<DefIdMap<DefId>>,
 }
 
@@ -112,7 +111,6 @@ pub fn new(dep_graph: &DepGraph) -> 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()),
         }
     }
 
index 64513fa41b219d03938faa1328369aa54df3b1c6..3d025e984b0400f903e76fe76a10ff2947647da4 100644 (file)
@@ -434,27 +434,14 @@ fn maybe_get_item_body<'a>(&'tcx self,
                                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<hir::BodyId, hir::Body> {
index dad956afb5e60ebbe8e505e2f70dde6c2ffc745f..f3a673898b25c10c112c67b14001057f7b945a3c 100644 (file)
 
 // 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 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<TyCtxt<'a, 'tcx, 'tcx>>,
-    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 @@ fn sess(self) -> Option<&'a Session> { None }
     fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> { 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 @@ fn tcx(self) -> Option<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<TyCtxt<'a, 'tcx, 'tcx>> {
-        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<T> {
     pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> T {
         let mut dcx = meta.decoder(self.position);
@@ -256,28 +226,6 @@ fn specialized_decode(&mut self) -> Result<LazySeq<T>, Self::Error> {
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<NodeId> for DecodeContext<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<NodeId, Self::Error> {
-        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<CrateNum> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
         let cnum = CrateNum::from_u32(u32::decode(self)?);
@@ -829,7 +777,14 @@ pub fn maybe_get_item_body(&self,
                                -> 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)
         })
     }
 
index aa5ebdf77a2abf4a4e2d0fc39f95bc981cb0d9ae..4b553a71b83259df57478b4a33273efe42a83dfa 100644 (file)
@@ -20,7 +20,6 @@
 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 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, src: MirSource) -> Cx<'a, 'gcx,
             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
index 2e2644d91bb6c3584aadeec23a53e7b52cbd6b53..a9c1edfdc66cc600ae6c7d9afffc2ac44ee02cb3 100644 (file)
@@ -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()
index f6428465eda203dbdd03823df5bbb8bb418a4af8..1473e55b2643cbef4b8f6aef5ccf759fe45d8cd8 100644 (file)
@@ -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);
 
index e7657fb16463c23525b5b8781e71fabc022b71a2..9e56bcc458d864fe88c8aabc0acea352c020ae1e 100644 (file)
@@ -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);
     });
 }
 
index 0f5f8d889e810e30bba4200d1fc16a2b256ec0fa..02ac7c196b5cb620945be4435ce98d2b04772a80 100644 (file)
 // 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 @@ pub fn resolve_type_vars_in_body(&self,
         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 @@ pub fn resolve_type_vars_in_body(&self,
 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 @@ fn tcx(&self) -> TyCtxt<'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 @@ fn visit_local(&mut self, l: &'gcx hir::Local) {
 
         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 @@ fn visit_upvar_borrow_map(&self) {
             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 @@ fn visit_anon_types(&self) {
         }
     }
 
-    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 @@ fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) {
         // 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 @@ fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) {
             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 @@ fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) {
                     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 @@ fn visit_method_map_entry(&self,
 
         //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);