about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-09-10 15:53:08 -0400
committerNiko Matsakis <niko@alum.mit.edu>2015-10-01 10:42:37 -0400
commitd7b0eb0f39861c47e2dce615197039e197417f17 (patch)
tree967799d797ab69b3d091f00775f789b86d309f6f
parenta0dc2d9a292189f1642f1d856203509a3019225b (diff)
downloadrust-d7b0eb0f39861c47e2dce615197039e197417f17.tar.gz
rust-d7b0eb0f39861c47e2dce615197039e197417f17.zip
build up a set of node-ids that we can construct def-ids from
-rw-r--r--src/librustc/front/map/collector.rs292
-rw-r--r--src/librustc/front/map/mod.rs258
-rw-r--r--src/librustc/middle/astencode.rs38
-rw-r--r--src/librustc/util/ppaux.rs4
-rw-r--r--src/librustc_lint/builtin.rs7
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/visit_ast.rs7
7 files changed, 371 insertions, 237 deletions
diff --git a/src/librustc/front/map/collector.rs b/src/librustc/front/map/collector.rs
new file mode 100644
index 00000000000..0dd51b4ec8a
--- /dev/null
+++ b/src/librustc/front/map/collector.rs
@@ -0,0 +1,292 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::*;
+use super::MapEntry::*;
+
+use rustc_front::hir::*;
+use rustc_front::util;
+use rustc_front::visit::{self, Visitor};
+use std::iter::repeat;
+use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
+use syntax::codemap::Span;
+use util::nodemap::NodeSet;
+
+/// A Visitor that walks over an AST and collects Node's into an AST
+/// Map.
+pub struct NodeCollector<'ast> {
+    pub map: Vec<MapEntry<'ast>>,
+    pub definitions_map: NodeSet,
+    pub parent_node: NodeId,
+}
+
+impl<'ast> NodeCollector<'ast> {
+    pub fn root() -> NodeCollector<'ast> {
+        let mut collector = NodeCollector {
+            map: vec![],
+            definitions_map: NodeSet(),
+            parent_node: CRATE_NODE_ID,
+        };
+        collector.insert_entry(CRATE_NODE_ID, RootCrate);
+        collector.create_def(CRATE_NODE_ID);
+        collector.create_def(DUMMY_NODE_ID);
+        collector
+    }
+
+    pub fn extend(parent: &'ast InlinedParent,
+                  parent_node: NodeId,
+                  map: Vec<MapEntry<'ast>>,
+                  definitions_map: NodeSet)
+                  -> NodeCollector<'ast> {
+        let mut collector = NodeCollector {
+            map: map,
+            definitions_map: definitions_map,
+            parent_node: parent_node
+        };
+        collector.insert_entry(parent_node, RootInlinedParent(parent));
+
+        collector
+    }
+
+    fn create_def(&mut self, node: NodeId) {
+        let is_new = self.definitions_map.insert(node);
+        assert!(is_new,
+                "two entries for node id `{}` -- previous is `{:?}`",
+                node, node);
+    }
+
+    fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
+        debug!("ast_map: {:?} => {:?}", id, entry);
+        let len = self.map.len();
+        if id as usize >= len {
+            self.map.extend(repeat(NotPresent).take(id as usize - len + 1));
+        }
+        self.map[id as usize] = entry;
+    }
+
+    fn insert(&mut self, id: NodeId, node: Node<'ast>) {
+        let entry = MapEntry::from_node(self.parent_node, node);
+        self.insert_entry(id, entry);
+    }
+
+    fn visit_fn_decl(&mut self, decl: &'ast FnDecl) {
+        for a in &decl.inputs {
+            self.insert(a.id, NodeArg(&*a.pat));
+        }
+    }
+}
+
+impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
+    fn visit_item(&mut self, i: &'ast Item) {
+        self.insert(i.id, NodeItem(i));
+
+        let parent_node = self.parent_node;
+        self.parent_node = i.id;
+
+        self.create_def(i.id);
+
+        match i.node {
+            ItemImpl(..) => { }
+            ItemEnum(ref enum_definition, _) => {
+                for v in &enum_definition.variants {
+                    self.insert(v.node.id, NodeVariant(&**v));
+                    self.create_def(v.node.id);
+
+                    match v.node.kind {
+                        TupleVariantKind(ref args) => {
+                            for arg in args {
+                                self.create_def(arg.id);
+                            }
+                        }
+                        StructVariantKind(ref def) => {
+                            for field in &def.fields {
+                                self.create_def(field.node.id);
+                            }
+                        }
+                    }
+                }
+            }
+            ItemForeignMod(..) => {}
+            ItemStruct(ref struct_def, _) => {
+                // If this is a tuple-like struct, register the constructor.
+                match struct_def.ctor_id {
+                    Some(ctor_id) => {
+                        self.insert(ctor_id, NodeStructCtor(&**struct_def));
+                        self.create_def(ctor_id);
+                    }
+                    None => {}
+                }
+
+                for field in &struct_def.fields {
+                    self.create_def(field.node.id);
+                }
+            }
+            ItemTrait(_, _, ref bounds, _) => {
+                for b in bounds.iter() {
+                    if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
+                        self.insert(t.trait_ref.ref_id, NodeItem(i));
+                    }
+                }
+            }
+            ItemUse(ref view_path) => {
+                match view_path.node {
+                    ViewPathList(_, ref paths) => {
+                        for path in paths {
+                            self.insert(path.node.id(), NodeItem(i));
+                        }
+                    }
+                    _ => ()
+                }
+            }
+            _ => {}
+        }
+        visit::walk_item(self, i);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
+        self.insert(foreign_item.id, NodeForeignItem(foreign_item));
+        self.create_def(foreign_item.id);
+
+        let parent_node = self.parent_node;
+        self.parent_node = foreign_item.id;
+        visit::walk_foreign_item(self, foreign_item);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_generics(&mut self, generics: &'ast Generics) {
+        for ty_param in generics.ty_params.iter() {
+            self.create_def(ty_param.id);
+            self.insert(ty_param.id, NodeTyParam(ty_param));
+        }
+
+        visit::walk_generics(self, generics);
+    }
+
+    fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
+        self.insert(ti.id, NodeTraitItem(ti));
+        self.create_def(ti.id);
+
+        match ti.node {
+            ConstTraitItem(_, Some(ref expr)) => {
+                self.create_def(expr.id);
+            }
+            _ => { }
+        }
+
+        let parent_node = self.parent_node;
+        self.parent_node = ti.id;
+        visit::walk_trait_item(self, ti);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
+        self.insert(ii.id, NodeImplItem(ii));
+        self.create_def(ii.id);
+
+        match ii.node {
+            ConstImplItem(_, ref expr) => {
+                self.create_def(expr.id);
+            }
+            _ => { }
+        }
+
+        let parent_node = self.parent_node;
+        self.parent_node = ii.id;
+        visit::walk_impl_item(self, ii);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_pat(&mut self, pat: &'ast Pat) {
+        let maybe_binding = match pat.node {
+            PatIdent(..) => true,
+            _ => false
+        };
+
+        self.insert(pat.id,
+                    if maybe_binding {NodeLocal(pat)} else {NodePat(pat)});
+
+        if maybe_binding {
+            self.create_def(pat.id);
+        }
+
+        let parent_node = self.parent_node;
+        self.parent_node = pat.id;
+        visit::walk_pat(self, pat);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_expr(&mut self, expr: &'ast Expr) {
+        self.insert(expr.id, NodeExpr(expr));
+
+        match expr.node {
+            ExprClosure(..) => self.create_def(expr.id),
+            _ => (),
+        }
+
+        let parent_node = self.parent_node;
+        self.parent_node = expr.id;
+        visit::walk_expr(self, expr);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_stmt(&mut self, stmt: &'ast Stmt) {
+        let id = util::stmt_id(stmt);
+        self.insert(id, NodeStmt(stmt));
+        let parent_node = self.parent_node;
+        self.parent_node = id;
+        visit::walk_stmt(self, stmt);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
+                b: &'ast Block, s: Span, id: NodeId) {
+        let parent_node = self.parent_node;
+        self.parent_node = id;
+        self.visit_fn_decl(fd);
+        visit::walk_fn(self, fk, fd, b, s);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_ty(&mut self, ty: &'ast Ty) {
+        let parent_node = self.parent_node;
+        self.parent_node = ty.id;
+        match ty.node {
+            TyBareFn(ref fd) => {
+                self.visit_fn_decl(&*fd.decl);
+            }
+            _ => {}
+        }
+        visit::walk_ty(self, ty);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_block(&mut self, block: &'ast Block) {
+        self.insert(block.id, NodeBlock(block));
+        let parent_node = self.parent_node;
+        self.parent_node = block.id;
+        visit::walk_block(self, block);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
+        self.insert(lifetime.id, NodeLifetime(lifetime));
+    }
+
+    fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
+        self.create_def(def.lifetime.id);
+        self.visit_lifetime(&def.lifetime);
+    }
+
+    fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
+        self.create_def(macro_def.id);
+    }
+}
+
diff --git a/src/librustc/front/map/mod.rs b/src/librustc/front/map/mod.rs
index b8d96cd3ba7..0486fd3a0d1 100644
--- a/src/librustc/front/map/mod.rs
+++ b/src/librustc/front/map/mod.rs
@@ -11,32 +11,34 @@
 pub use self::Node::*;
 pub use self::PathElem::*;
 use self::MapEntry::*;
+use self::collector::NodeCollector;
 
 use metadata::cstore::LOCAL_CRATE;
 use metadata::inline::InlinedItem;
 use metadata::inline::InlinedItem as II;
 use middle::def_id::DefId;
+use util::nodemap::NodeSet;
 
 use syntax::abi;
-use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
+use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID};
 use syntax::codemap::{Span, Spanned};
 use syntax::parse::token;
 
 use rustc_front::hir::*;
 use rustc_front::fold::Folder;
-use rustc_front::visit::{self, Visitor};
-use rustc_front::util;
+use rustc_front::visit;
 use rustc_front::print::pprust;
 
 use arena::TypedArena;
 use std::cell::RefCell;
 use std::fmt;
 use std::io;
-use std::iter::{self, repeat};
+use std::iter;
 use std::mem;
 use std::slice;
 
 pub mod blocks;
+mod collector;
 
 #[derive(Clone, Copy, PartialEq, Debug)]
 pub enum PathElem {
@@ -131,7 +133,7 @@ pub enum Node<'ast> {
 /// Represents an entry and its parent NodeID.
 /// The odd layout is to bring down the total size.
 #[derive(Copy, Debug)]
-enum MapEntry<'ast> {
+pub enum MapEntry<'ast> {
     /// Placeholder for holes in the map.
     NotPresent,
 
@@ -264,22 +266,46 @@ 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: RefCell<Vec<MapEntry<'ast>>>,
+
+    definitions_map: RefCell<NodeSet>,
 }
 
 impl<'ast> Map<'ast> {
     pub fn local_def_id(&self, node: NodeId) -> DefId {
-        DefId::xxx_local(node)
+        self.opt_local_def_id(node).unwrap_or_else(|| {
+            panic!("local_def_id: no entry for `{}`, which has a map of `{:?}`",
+                   node, self.find_entry(node))
+        })
+    }
+
+    pub fn opt_local_def_id(&self, node: NodeId) -> Option<DefId> {
+        if self.definitions_map.borrow().contains(&node) {
+            Some(DefId::xxx_local(node))
+        } else {
+            None
+        }
     }
 
     pub fn as_local_node_id(&self, def_id: DefId) -> Option<NodeId> {
         if def_id.krate == LOCAL_CRATE {
+            assert!(self.definitions_map.borrow().contains(&def_id.xxx_node));
             Some(def_id.xxx_node)
         } else {
             None
         }
     }
 
+    /// for default methods, we create a fake node-id; this method
+    /// adds that fake node-id to the def-id tables
+    pub fn synthesize_default_method_def_id(&self,
+                                            _impl_def_id: DefId,
+                                            new_method_id: NodeId)
+                                            -> DefId {
+        self.definitions_map.borrow_mut().insert(new_method_id);
+        DefId::xxx_local(new_method_id)
+    }
+
     fn entry_count(&self) -> usize {
         self.map.borrow().len()
     }
@@ -762,194 +788,10 @@ impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
     }
 }
 
-/// A Visitor that walks over an AST and collects Node's into an AST Map.
-struct NodeCollector<'ast> {
-    map: Vec<MapEntry<'ast>>,
-    parent_node: NodeId,
-}
-
-impl<'ast> NodeCollector<'ast> {
-    fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
-        debug!("ast_map: {:?} => {:?}", id, entry);
-        let len = self.map.len();
-        if id as usize >= len {
-            self.map.extend(repeat(NotPresent).take(id as usize - len + 1));
-        }
-        self.map[id as usize] = entry;
-    }
-
-    fn insert(&mut self, id: NodeId, node: Node<'ast>) {
-        let entry = MapEntry::from_node(self.parent_node, node);
-        self.insert_entry(id, entry);
-    }
-
-    fn visit_fn_decl(&mut self, decl: &'ast FnDecl) {
-        for a in &decl.inputs {
-            self.insert(a.id, NodeArg(&*a.pat));
-        }
-    }
-}
-
-impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
-    fn visit_item(&mut self, i: &'ast Item) {
-        self.insert(i.id, NodeItem(i));
-
-        let parent_node = self.parent_node;
-        self.parent_node = i.id;
-
-        match i.node {
-            ItemImpl(_, _, _, _, _, ref impl_items) => {
-                for ii in impl_items {
-                    self.insert(ii.id, NodeImplItem(ii));
-                }
-            }
-            ItemEnum(ref enum_definition, _) => {
-                for v in &enum_definition.variants {
-                    self.insert(v.node.id, NodeVariant(&**v));
-                }
-            }
-            ItemForeignMod(ref nm) => {
-                for nitem in &nm.items {
-                    self.insert(nitem.id, NodeForeignItem(&**nitem));
-                }
-            }
-            ItemStruct(ref struct_def, _) => {
-                // If this is a tuple-like struct, register the constructor.
-                match struct_def.ctor_id {
-                    Some(ctor_id) => {
-                        self.insert(ctor_id, NodeStructCtor(&**struct_def));
-                    }
-                    None => {}
-                }
-            }
-            ItemTrait(_, _, ref bounds, ref trait_items) => {
-                for b in bounds.iter() {
-                    if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
-                        self.insert(t.trait_ref.ref_id, NodeItem(i));
-                    }
-                }
-
-                for ti in trait_items {
-                    self.insert(ti.id, NodeTraitItem(ti));
-                }
-            }
-            ItemUse(ref view_path) => {
-                match view_path.node {
-                    ViewPathList(_, ref paths) => {
-                        for path in paths {
-                            self.insert(path.node.id(), NodeItem(i));
-                        }
-                    }
-                    _ => ()
-                }
-            }
-            _ => {}
-        }
-        visit::walk_item(self, i);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_generics(&mut self, generics: &'ast Generics) {
-        for ty_param in generics.ty_params.iter() {
-            self.insert(ty_param.id, NodeTyParam(ty_param));
-        }
-
-        visit::walk_generics(self, generics);
-    }
-
-    fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
-        let parent_node = self.parent_node;
-        self.parent_node = ti.id;
-        visit::walk_trait_item(self, ti);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
-        let parent_node = self.parent_node;
-        self.parent_node = ii.id;
-
-        visit::walk_impl_item(self, ii);
-
-        self.parent_node = parent_node;
-    }
-
-    fn visit_pat(&mut self, pat: &'ast Pat) {
-        self.insert(pat.id, match pat.node {
-            // Note: this is at least *potentially* a pattern...
-            PatIdent(..) => NodeLocal(pat),
-            _ => NodePat(pat)
-        });
-
-        let parent_node = self.parent_node;
-        self.parent_node = pat.id;
-        visit::walk_pat(self, pat);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_expr(&mut self, expr: &'ast Expr) {
-        self.insert(expr.id, NodeExpr(expr));
-        let parent_node = self.parent_node;
-        self.parent_node = expr.id;
-        visit::walk_expr(self, expr);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_stmt(&mut self, stmt: &'ast Stmt) {
-        let id = util::stmt_id(stmt);
-        self.insert(id, NodeStmt(stmt));
-        let parent_node = self.parent_node;
-        self.parent_node = id;
-        visit::walk_stmt(self, stmt);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
-                b: &'ast Block, s: Span, id: NodeId) {
-        let parent_node = self.parent_node;
-        self.parent_node = id;
-        self.visit_fn_decl(fd);
-        visit::walk_fn(self, fk, fd, b, s);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_ty(&mut self, ty: &'ast Ty) {
-        let parent_node = self.parent_node;
-        self.parent_node = ty.id;
-        match ty.node {
-            TyBareFn(ref fd) => {
-                self.visit_fn_decl(&*fd.decl);
-            }
-            _ => {}
-        }
-        visit::walk_ty(self, ty);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_block(&mut self, block: &'ast Block) {
-        self.insert(block.id, NodeBlock(block));
-        let parent_node = self.parent_node;
-        self.parent_node = block.id;
-        visit::walk_block(self, block);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
-        self.insert(lifetime.id, NodeLifetime(lifetime));
-    }
-
-    fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
-        self.visit_lifetime(&def.lifetime);
-    }
-}
-
 pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
-    let mut collector = NodeCollector {
-        map: vec![],
-        parent_node: CRATE_NODE_ID,
-    };
-    collector.insert_entry(CRATE_NODE_ID, RootCrate);
+    let mut collector = NodeCollector::root();
     visit::walk_crate(&mut collector, &forest.krate);
-    let map = collector.map;
+    let NodeCollector { map, definitions_map, .. } = collector;
 
     if log_enabled!(::log::DEBUG) {
         // This only makes sense for ordered stores; note the
@@ -969,7 +811,8 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
 
     Map {
         forest: forest,
-        map: RefCell::new(map)
+        map: RefCell::new(map),
+        definitions_map: RefCell::new(definitions_map),
     }
 }
 
@@ -1001,29 +844,16 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
     });
 
     let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
-    let mut collector = NodeCollector {
-        map: mem::replace(&mut *map.map.borrow_mut(), vec![]),
-        parent_node: ii_parent_id,
-    };
-    collector.insert_entry(ii_parent_id, RootInlinedParent(ii_parent));
+    let mut collector =
+        NodeCollector::extend(ii_parent,
+                              ii_parent_id,
+                              mem::replace(&mut *map.map.borrow_mut(), vec![]),
+                              mem::replace(&mut *map.definitions_map.borrow_mut(), NodeSet()));
     ii_parent.ii.visit(&mut collector);
 
-    // Methods get added to the AST map when their impl is visited.  Since we
-    // don't decode and instantiate the impl, but just the method, we have to
-    // add it to the table now. Likewise with foreign items.
-    match ii_parent.ii {
-        II::Item(_) => {}
-        II::TraitItem(_, ref ti) => {
-            collector.insert(ti.id, NodeTraitItem(ti));
-        }
-        II::ImplItem(_, ref ii) => {
-            collector.insert(ii.id, NodeImplItem(ii));
-        }
-        II::Foreign(ref i) => {
-            collector.insert(i.id, NodeForeignItem(i));
-        }
-    }
     *map.map.borrow_mut() = collector.map;
+    *map.definitions_map.borrow_mut() = collector.definitions_map;
+
     &ii_parent.ii
 }
 
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 0b72b0d9542..02bd9951d34 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -957,12 +957,14 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         }
     }
 
-    let lid = tcx.map.local_def_id(id);
-    if let Some(type_scheme) = tcx.tcache.borrow().get(&lid) {
-        rbml_w.tag(c::tag_table_tcache, |rbml_w| {
-            rbml_w.id(id);
-            rbml_w.emit_type_scheme(ecx, type_scheme.clone());
-        })
+    let opt_def_id = tcx.map.opt_local_def_id(id);
+    if let Some(lid) = opt_def_id {
+        if let Some(type_scheme) = tcx.tcache.borrow().get(&lid) {
+            rbml_w.tag(c::tag_table_tcache, |rbml_w| {
+                rbml_w.id(id);
+                rbml_w.emit_type_scheme(ecx, type_scheme.clone());
+            })
+        }
     }
 
     if let Some(type_param_def) = tcx.ty_param_defs.borrow().get(&id) {
@@ -1003,18 +1005,22 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         })
     }
 
-    if let Some(closure_type) = tcx.tables.borrow().closure_tys.get(&tcx.map.local_def_id(id)) {
-        rbml_w.tag(c::tag_table_closure_tys, |rbml_w| {
-            rbml_w.id(id);
-            rbml_w.emit_closure_type(ecx, closure_type);
-        })
+    if let Some(def_id) = opt_def_id {
+        if let Some(closure_type) = tcx.tables.borrow().closure_tys.get(&def_id) {
+            rbml_w.tag(c::tag_table_closure_tys, |rbml_w| {
+                rbml_w.id(id);
+                rbml_w.emit_closure_type(ecx, closure_type);
+            })
+        }
     }
 
-    if let Some(closure_kind) = tcx.tables.borrow().closure_kinds.get(&tcx.map.local_def_id(id)) {
-        rbml_w.tag(c::tag_table_closure_kinds, |rbml_w| {
-            rbml_w.id(id);
-            encode_closure_kind(rbml_w, *closure_kind)
-        })
+    if let Some(def_id) = opt_def_id {
+        if let Some(closure_kind) = tcx.tables.borrow().closure_kinds.get(&def_id) {
+            rbml_w.tag(c::tag_table_closure_kinds, |rbml_w| {
+                rbml_w.id(id);
+                encode_closure_kind(rbml_w, *closure_kind)
+            })
+        }
     }
 
     if let Some(cast_kind) = tcx.cast_kinds.borrow().get(&id) {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index e4eba8aefcc..de356e54699 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -27,7 +27,7 @@ use std::fmt;
 use syntax::abi;
 use syntax::ast;
 use syntax::parse::token;
-use syntax::ast::DUMMY_NODE_ID;
+use syntax::ast::{CRATE_NODE_ID};
 use rustc_front::hir;
 
 pub fn verbose() -> bool {
@@ -232,7 +232,7 @@ fn in_binder<'tcx, T, U>(f: &mut fmt::Formatter,
             ty::BrEnv => {
                 let name = token::intern("'r");
                 let _ = write!(f, "{}", name);
-                ty::BrNamed(tcx.map.local_def_id(DUMMY_NODE_ID), name)
+                ty::BrNamed(tcx.map.local_def_id(CRATE_NODE_ID), name)
             }
         })
     }).0;
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 8c5c4cce167..d05b5b3e860 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -248,8 +248,11 @@ impl LateLintPass for NonShorthandFieldPatterns {
                     return false;
                 }
                 let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def());
-                let def_id = cx.tcx.map.local_def_id(fieldpat.node.pat.id);
-                def == Some(def::DefLocal(def_id, fieldpat.node.pat.id))
+                if let Some(def_id) = cx.tcx.map.opt_local_def_id(fieldpat.node.pat.id) {
+                    def == Some(def::DefLocal(def_id, fieldpat.node.pat.id))
+                } else {
+                    false
+                }
             });
             for fieldpat in field_pats {
                 if let hir::PatIdent(_, ident, None) = fieldpat.node.pat.node {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2b6a8f3fe52..dab4056b4af 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -188,7 +188,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
                     attrs: child.attrs.clone(),
                     visibility: Some(hir::Public),
                     stability: None,
-                    def_id: cx.map.local_def_id(prim.to_node_id()),
+                    def_id: DefId::xxx_local(prim.to_node_id()),
                     inner: PrimitiveItem(prim),
                 });
             }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 9972ede8b8f..264656835a3 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -62,8 +62,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     }
 
     fn stability(&self, id: ast::NodeId) -> Option<attr::Stability> {
-        self.cx.tcx_opt().and_then(
-            |tcx| stability::lookup(tcx, self.cx.map.local_def_id(id)).map(|x| x.clone()))
+        self.cx.tcx_opt().and_then(|tcx| {
+            self.cx.map.opt_local_def_id(id)
+                       .and_then(|def_id| stability::lookup(tcx, def_id))
+                       .cloned()
+        })
     }
 
     pub fn visit(&mut self, krate: &hir::Crate) {