]> git.lizzy.rs Git - rust.git/blob - src/librustc/hir/map/mod.rs
Auto merge of #35856 - phimuemue:master, r=brson
[rust.git] / src / librustc / hir / map / mod.rs
1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 pub use self::Node::*;
12 use self::MapEntry::*;
13 use self::collector::NodeCollector;
14 use self::def_collector::DefCollector;
15 pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
16                             DisambiguatedDefPathData, InlinedRootPath};
17
18 use dep_graph::{DepGraph, DepNode};
19
20 use middle::cstore::InlinedItem;
21 use middle::cstore::InlinedItem as II;
22 use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
23
24 use syntax::abi::Abi;
25 use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, };
26 use syntax::codemap::Spanned;
27 use syntax_pos::Span;
28
29 use hir::*;
30 use hir::fold::Folder;
31 use hir::print as pprust;
32
33 use arena::TypedArena;
34 use std::cell::RefCell;
35 use std::cmp;
36 use std::io;
37 use std::mem;
38
39 pub mod blocks;
40 mod collector;
41 mod def_collector;
42 pub mod definitions;
43
44 #[derive(Copy, Clone, Debug)]
45 pub enum Node<'ast> {
46     NodeItem(&'ast Item),
47     NodeForeignItem(&'ast ForeignItem),
48     NodeTraitItem(&'ast TraitItem),
49     NodeImplItem(&'ast ImplItem),
50     NodeVariant(&'ast Variant),
51     NodeExpr(&'ast Expr),
52     NodeStmt(&'ast Stmt),
53     NodeTy(&'ast Ty),
54     NodeLocal(&'ast Pat),
55     NodePat(&'ast Pat),
56     NodeBlock(&'ast Block),
57
58     /// NodeStructCtor represents a tuple struct.
59     NodeStructCtor(&'ast VariantData),
60
61     NodeLifetime(&'ast Lifetime),
62     NodeTyParam(&'ast TyParam)
63 }
64
65 /// Represents an entry and its parent NodeID.
66 /// The odd layout is to bring down the total size.
67 #[derive(Copy, Debug)]
68 pub enum MapEntry<'ast> {
69     /// Placeholder for holes in the map.
70     NotPresent,
71
72     /// All the node types, with a parent ID.
73     EntryItem(NodeId, &'ast Item),
74     EntryForeignItem(NodeId, &'ast ForeignItem),
75     EntryTraitItem(NodeId, &'ast TraitItem),
76     EntryImplItem(NodeId, &'ast ImplItem),
77     EntryVariant(NodeId, &'ast Variant),
78     EntryExpr(NodeId, &'ast Expr),
79     EntryStmt(NodeId, &'ast Stmt),
80     EntryTy(NodeId, &'ast Ty),
81     EntryLocal(NodeId, &'ast Pat),
82     EntryPat(NodeId, &'ast Pat),
83     EntryBlock(NodeId, &'ast Block),
84     EntryStructCtor(NodeId, &'ast VariantData),
85     EntryLifetime(NodeId, &'ast Lifetime),
86     EntryTyParam(NodeId, &'ast TyParam),
87
88     /// Roots for node trees.
89     RootCrate,
90     RootInlinedParent(&'ast InlinedItem)
91 }
92
93 impl<'ast> Clone for MapEntry<'ast> {
94     fn clone(&self) -> MapEntry<'ast> {
95         *self
96     }
97 }
98
99 impl<'ast> MapEntry<'ast> {
100     fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
101         match node {
102             NodeItem(n) => EntryItem(p, n),
103             NodeForeignItem(n) => EntryForeignItem(p, n),
104             NodeTraitItem(n) => EntryTraitItem(p, n),
105             NodeImplItem(n) => EntryImplItem(p, n),
106             NodeVariant(n) => EntryVariant(p, n),
107             NodeExpr(n) => EntryExpr(p, n),
108             NodeStmt(n) => EntryStmt(p, n),
109             NodeTy(n) => EntryTy(p, n),
110             NodeLocal(n) => EntryLocal(p, n),
111             NodePat(n) => EntryPat(p, n),
112             NodeBlock(n) => EntryBlock(p, n),
113             NodeStructCtor(n) => EntryStructCtor(p, n),
114             NodeLifetime(n) => EntryLifetime(p, n),
115             NodeTyParam(n) => EntryTyParam(p, n),
116         }
117     }
118
119     fn parent_node(self) -> Option<NodeId> {
120         Some(match self {
121             EntryItem(id, _) => id,
122             EntryForeignItem(id, _) => id,
123             EntryTraitItem(id, _) => id,
124             EntryImplItem(id, _) => id,
125             EntryVariant(id, _) => id,
126             EntryExpr(id, _) => id,
127             EntryStmt(id, _) => id,
128             EntryTy(id, _) => id,
129             EntryLocal(id, _) => id,
130             EntryPat(id, _) => id,
131             EntryBlock(id, _) => id,
132             EntryStructCtor(id, _) => id,
133             EntryLifetime(id, _) => id,
134             EntryTyParam(id, _) => id,
135
136             NotPresent |
137             RootCrate |
138             RootInlinedParent(_) => return None,
139         })
140     }
141
142     fn to_node(self) -> Option<Node<'ast>> {
143         Some(match self {
144             EntryItem(_, n) => NodeItem(n),
145             EntryForeignItem(_, n) => NodeForeignItem(n),
146             EntryTraitItem(_, n) => NodeTraitItem(n),
147             EntryImplItem(_, n) => NodeImplItem(n),
148             EntryVariant(_, n) => NodeVariant(n),
149             EntryExpr(_, n) => NodeExpr(n),
150             EntryStmt(_, n) => NodeStmt(n),
151             EntryTy(_, n) => NodeTy(n),
152             EntryLocal(_, n) => NodeLocal(n),
153             EntryPat(_, n) => NodePat(n),
154             EntryBlock(_, n) => NodeBlock(n),
155             EntryStructCtor(_, n) => NodeStructCtor(n),
156             EntryLifetime(_, n) => NodeLifetime(n),
157             EntryTyParam(_, n) => NodeTyParam(n),
158             _ => return None
159         })
160     }
161 }
162
163 /// Stores a crate and any number of inlined items from other crates.
164 pub struct Forest {
165     krate: Crate,
166     pub dep_graph: DepGraph,
167     inlined_items: TypedArena<InlinedItem>
168 }
169
170 impl Forest {
171     pub fn new(krate: Crate, dep_graph: &DepGraph) -> Forest {
172         Forest {
173             krate: krate,
174             dep_graph: dep_graph.clone(),
175             inlined_items: TypedArena::new()
176         }
177     }
178
179     pub fn krate<'ast>(&'ast self) -> &'ast Crate {
180         self.dep_graph.read(DepNode::Krate);
181         &self.krate
182     }
183 }
184
185 /// Represents a mapping from Node IDs to AST elements and their parent
186 /// Node IDs
187 #[derive(Clone)]
188 pub struct Map<'ast> {
189     /// The backing storage for all the AST nodes.
190     pub forest: &'ast Forest,
191
192     /// Same as the dep_graph in forest, just available with one fewer
193     /// deref. This is a gratuitious micro-optimization.
194     pub dep_graph: DepGraph,
195
196     /// NodeIds are sequential integers from 0, so we can be
197     /// super-compact by storing them in a vector. Not everything with
198     /// a NodeId is in the map, but empirically the occupancy is about
199     /// 75-80%, so there's not too much overhead (certainly less than
200     /// a hashmap, since they (at the time of writing) have a maximum
201     /// of 75% occupancy).
202     ///
203     /// Also, indexing is pretty quick when you've got a vector and
204     /// plain old integers.
205     map: RefCell<Vec<MapEntry<'ast>>>,
206
207     definitions: RefCell<Definitions>,
208
209     /// All NodeIds that are numerically greater or equal to this value come
210     /// from inlined items.
211     local_node_id_watermark: NodeId,
212
213     /// All def-indices that are numerically greater or equal to this value come
214     /// from inlined items.
215     local_def_id_watermark: usize,
216 }
217
218 impl<'ast> Map<'ast> {
219     pub fn is_inlined_def_id(&self, id: DefId) -> bool {
220         id.is_local() && id.index.as_usize() >= self.local_def_id_watermark
221     }
222
223     pub fn is_inlined_node_id(&self, id: NodeId) -> bool {
224         id >= self.local_node_id_watermark
225     }
226
227     /// Registers a read in the dependency graph of the AST node with
228     /// the given `id`. This needs to be called each time a public
229     /// function returns the HIR for a node -- in other words, when it
230     /// "reveals" the content of a node to the caller (who might not
231     /// otherwise have had access to those contents, and hence needs a
232     /// read recorded). If the function just returns a DefId or
233     /// NodeId, no actual content was returned, so no read is needed.
234     pub fn read(&self, id: NodeId) {
235         self.dep_graph.read(self.dep_node(id));
236     }
237
238     fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
239         let map = self.map.borrow();
240         let mut id = id0;
241         if !self.is_inlined_node_id(id) {
242             loop {
243                 match map[id as usize] {
244                     EntryItem(_, item) => {
245                         let def_id = self.local_def_id(item.id);
246                         // NB                          ^~~~~~~
247                         //
248                         // You would expect that `item.id == id`, but this
249                         // is not always the case. In particular, for a
250                         // ViewPath item like `use self::{mem, foo}`, we
251                         // map the ids for `mem` and `foo` to the
252                         // enclosing view path item. This seems mega super
253                         // ultra wrong, but then who am I to judge?
254                         // -nmatsakis
255                         assert!(!self.is_inlined_def_id(def_id));
256                         return DepNode::Hir(def_id);
257                     }
258
259                     EntryForeignItem(p, _) |
260                     EntryTraitItem(p, _) |
261                     EntryImplItem(p, _) |
262                     EntryVariant(p, _) |
263                     EntryExpr(p, _) |
264                     EntryStmt(p, _) |
265                 EntryTy(p, _) |
266                     EntryLocal(p, _) |
267                     EntryPat(p, _) |
268                     EntryBlock(p, _) |
269                     EntryStructCtor(p, _) |
270                     EntryLifetime(p, _) |
271                     EntryTyParam(p, _) =>
272                         id = p,
273
274                     RootCrate =>
275                         return DepNode::Krate,
276
277                     RootInlinedParent(_) =>
278                         bug!("node {} has inlined ancestor but is not inlined", id0),
279
280                     NotPresent =>
281                         // Some nodes, notably struct fields, are not
282                         // present in the map for whatever reason, but
283                         // they *do* have def-ids. So if we encounter an
284                         // empty hole, check for that case.
285                         return self.opt_local_def_id(id)
286                                    .map(|def_id| DepNode::Hir(def_id))
287                                    .unwrap_or_else(|| {
288                                        bug!("Walking parents from `{}` \
289                                              led to `NotPresent` at `{}`",
290                                             id0, id)
291                                    }),
292                 }
293             }
294         } else {
295             // reading from an inlined def-id is really a read out of
296             // the metadata from which we loaded the item.
297             loop {
298                 match map[id as usize] {
299                     EntryItem(p, _) |
300                     EntryForeignItem(p, _) |
301                     EntryTraitItem(p, _) |
302                     EntryImplItem(p, _) |
303                     EntryVariant(p, _) |
304                     EntryExpr(p, _) |
305                     EntryStmt(p, _) |
306                     EntryTy(p, _) |
307                     EntryLocal(p, _) |
308                     EntryPat(p, _) |
309                     EntryBlock(p, _) |
310                     EntryStructCtor(p, _) |
311                     EntryLifetime(p, _) |
312                     EntryTyParam(p, _) =>
313                         id = p,
314
315                     RootInlinedParent(parent) => match *parent {
316                         InlinedItem::Item(def_id, _) |
317                         InlinedItem::TraitItem(def_id, _) |
318                         InlinedItem::ImplItem(def_id, _) =>
319                             return DepNode::MetaData(def_id)
320                     },
321
322                     RootCrate =>
323                         bug!("node {} has crate ancestor but is inlined", id0),
324
325                     NotPresent =>
326                         bug!("node {} is inlined but not present in map", id0),
327                 }
328             }
329         }
330     }
331
332     pub fn num_local_def_ids(&self) -> usize {
333         self.definitions.borrow().len()
334     }
335
336     pub fn def_key(&self, def_id: DefId) -> DefKey {
337         assert!(def_id.is_local());
338         self.definitions.borrow().def_key(def_id.index)
339     }
340
341     pub fn def_path_from_id(&self, id: NodeId) -> Option<DefPath> {
342         self.opt_local_def_id(id).map(|def_id| {
343             self.def_path(def_id)
344         })
345     }
346
347     pub fn def_path(&self, def_id: DefId) -> DefPath {
348         assert!(def_id.is_local());
349         self.definitions.borrow().def_path(def_id.index)
350     }
351
352     pub fn def_index_for_def_key(&self, def_key: DefKey) -> Option<DefIndex> {
353         self.definitions.borrow().def_index_for_def_key(def_key)
354     }
355
356     pub fn local_def_id(&self, node: NodeId) -> DefId {
357         self.opt_local_def_id(node).unwrap_or_else(|| {
358             bug!("local_def_id: no entry for `{}`, which has a map of `{:?}`",
359                  node, self.find_entry(node))
360         })
361     }
362
363     pub fn opt_local_def_id(&self, node: NodeId) -> Option<DefId> {
364         self.definitions.borrow().opt_local_def_id(node)
365     }
366
367     pub fn as_local_node_id(&self, def_id: DefId) -> Option<NodeId> {
368         self.definitions.borrow().as_local_node_id(def_id)
369     }
370
371     fn entry_count(&self) -> usize {
372         self.map.borrow().len()
373     }
374
375     fn find_entry(&self, id: NodeId) -> Option<MapEntry<'ast>> {
376         self.map.borrow().get(id as usize).cloned()
377     }
378
379     pub fn krate(&self) -> &'ast Crate {
380         self.forest.krate()
381     }
382
383     /// Get the attributes on the krate. This is preferable to
384     /// invoking `krate.attrs` because it registers a tighter
385     /// dep-graph access.
386     pub fn krate_attrs(&self) -> &'ast [ast::Attribute] {
387         let crate_root_def_id = DefId::local(CRATE_DEF_INDEX);
388         self.dep_graph.read(DepNode::Hir(crate_root_def_id));
389         &self.forest.krate.attrs
390     }
391
392     /// Retrieve the Node corresponding to `id`, panicking if it cannot
393     /// be found.
394     pub fn get(&self, id: NodeId) -> Node<'ast> {
395         match self.find(id) {
396             Some(node) => node, // read recorded by `find`
397             None => bug!("couldn't find node id {} in the AST map", id)
398         }
399     }
400
401     pub fn get_if_local(&self, id: DefId) -> Option<Node<'ast>> {
402         self.as_local_node_id(id).map(|id| self.get(id)) // read recorded by `get`
403     }
404
405     /// Retrieve the Node corresponding to `id`, returning None if
406     /// cannot be found.
407     pub fn find(&self, id: NodeId) -> Option<Node<'ast>> {
408         let result = self.find_entry(id).and_then(|x| x.to_node());
409         if result.is_some() {
410             self.read(id);
411         }
412         result
413     }
414
415     /// Similar to get_parent, returns the parent node id or id if there is no
416     /// parent.
417     /// This function returns the immediate parent in the AST, whereas get_parent
418     /// returns the enclosing item. Note that this might not be the actual parent
419     /// node in the AST - some kinds of nodes are not in the map and these will
420     /// never appear as the parent_node. So you can always walk the parent_nodes
421     /// from a node to the root of the ast (unless you get the same id back here
422     /// that can happen if the id is not in the map itself or is just weird).
423     pub fn get_parent_node(&self, id: NodeId) -> NodeId {
424         self.find_entry(id).and_then(|x| x.parent_node()).unwrap_or(id)
425     }
426
427     /// Check if the node is an argument. An argument is a local variable whose
428     /// immediate parent is an item or a closure.
429     pub fn is_argument(&self, id: NodeId) -> bool {
430         match self.find(id) {
431             Some(NodeLocal(_)) => (),
432             _ => return false,
433         }
434         match self.find(self.get_parent_node(id)) {
435             Some(NodeItem(_)) |
436             Some(NodeTraitItem(_)) |
437             Some(NodeImplItem(_)) => true,
438             Some(NodeExpr(e)) => {
439                 match e.node {
440                     ExprClosure(..) => true,
441                     _ => false,
442                 }
443             }
444             _ => false,
445         }
446     }
447
448     /// If there is some error when walking the parents (e.g., a node does not
449     /// have a parent in the map or a node can't be found), then we return the
450     /// last good node id we found. Note that reaching the crate root (id == 0),
451     /// is not an error, since items in the crate module have the crate root as
452     /// parent.
453     fn walk_parent_nodes<F>(&self, start_id: NodeId, found: F) -> Result<NodeId, NodeId>
454         where F: Fn(&Node<'ast>) -> bool
455     {
456         let mut id = start_id;
457         loop {
458             let parent_node = self.get_parent_node(id);
459             if parent_node == 0 {
460                 return Ok(0);
461             }
462             if parent_node == id {
463                 return Err(id);
464             }
465
466             let node = self.find_entry(parent_node);
467             if node.is_none() {
468                 return Err(id);
469             }
470             let node = node.unwrap().to_node();
471             match node {
472                 Some(ref node) => {
473                     if found(node) {
474                         return Ok(parent_node);
475                     }
476                 }
477                 None => {
478                     return Err(parent_node);
479                 }
480             }
481             id = parent_node;
482         }
483     }
484
485     /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
486     /// parent item is in this map. The "parent item" is the closest parent node
487     /// in the AST which is recorded by the map and is an item, either an item
488     /// in a module, trait, or impl.
489     pub fn get_parent(&self, id: NodeId) -> NodeId {
490         match self.walk_parent_nodes(id, |node| match *node {
491             NodeItem(_) |
492             NodeForeignItem(_) |
493             NodeTraitItem(_) |
494             NodeImplItem(_) => true,
495             _ => false,
496         }) {
497             Ok(id) => id,
498             Err(id) => id,
499         }
500     }
501
502     /// Returns the NodeId of `id`'s nearest module parent, or `id` itself if no
503     /// module parent is in this map.
504     pub fn get_module_parent(&self, id: NodeId) -> NodeId {
505         match self.walk_parent_nodes(id, |node| match *node {
506             NodeItem(&Item { node: Item_::ItemMod(_), .. }) => true,
507             _ => false,
508         }) {
509             Ok(id) => id,
510             Err(id) => id,
511         }
512     }
513
514     /// Returns the nearest enclosing scope. A scope is an item or block.
515     /// FIXME it is not clear to me that all items qualify as scopes - statics
516     /// and associated types probably shouldn't, for example. Behaviour in this
517     /// regard should be expected to be highly unstable.
518     pub fn get_enclosing_scope(&self, id: NodeId) -> Option<NodeId> {
519         match self.walk_parent_nodes(id, |node| match *node {
520             NodeItem(_) |
521             NodeForeignItem(_) |
522             NodeTraitItem(_) |
523             NodeImplItem(_) |
524             NodeBlock(_) => true,
525             _ => false,
526         }) {
527             Ok(id) => Some(id),
528             Err(_) => None,
529         }
530     }
531
532     pub fn get_parent_did(&self, id: NodeId) -> DefId {
533         let parent = self.get_parent(id);
534         match self.find_entry(parent) {
535             Some(RootInlinedParent(&II::TraitItem(did, _))) |
536             Some(RootInlinedParent(&II::ImplItem(did, _))) => did,
537             _ => self.local_def_id(parent)
538         }
539     }
540
541     pub fn get_foreign_abi(&self, id: NodeId) -> Abi {
542         let parent = self.get_parent(id);
543         let abi = match self.find_entry(parent) {
544             Some(EntryItem(_, i)) => {
545                 match i.node {
546                     ItemForeignMod(ref nm) => Some(nm.abi),
547                     _ => None
548                 }
549             }
550             /// Wrong but OK, because the only inlined foreign items are intrinsics.
551             Some(RootInlinedParent(_)) => Some(Abi::RustIntrinsic),
552             _ => None
553         };
554         match abi {
555             Some(abi) => {
556                 self.read(id); // reveals some of the content of a node
557                 abi
558             }
559             None => bug!("expected foreign mod or inlined parent, found {}",
560                           self.node_to_string(parent))
561         }
562     }
563
564     pub fn expect_item(&self, id: NodeId) -> &'ast Item {
565         match self.find(id) { // read recorded by `find`
566             Some(NodeItem(item)) => item,
567             _ => bug!("expected item, found {}", self.node_to_string(id))
568         }
569     }
570
571     pub fn expect_impl_item(&self, id: NodeId) -> &'ast ImplItem {
572         match self.find(id) {
573             Some(NodeImplItem(item)) => item,
574             _ => bug!("expected impl item, found {}", self.node_to_string(id))
575         }
576     }
577
578     pub fn expect_trait_item(&self, id: NodeId) -> &'ast TraitItem {
579         match self.find(id) {
580             Some(NodeTraitItem(item)) => item,
581             _ => bug!("expected trait item, found {}", self.node_to_string(id))
582         }
583     }
584
585     pub fn expect_struct(&self, id: NodeId) -> &'ast VariantData {
586         match self.find(id) {
587             Some(NodeItem(i)) => {
588                 match i.node {
589                     ItemStruct(ref struct_def, _) => struct_def,
590                     _ => bug!("struct ID bound to non-struct")
591                 }
592             }
593             Some(NodeVariant(variant)) => {
594                 if variant.node.data.is_struct() {
595                     &variant.node.data
596                 } else {
597                     bug!("struct ID bound to enum variant that isn't struct-like")
598                 }
599             }
600             _ => bug!("expected struct, found {}", self.node_to_string(id)),
601         }
602     }
603
604     pub fn expect_variant(&self, id: NodeId) -> &'ast Variant {
605         match self.find(id) {
606             Some(NodeVariant(variant)) => variant,
607             _ => bug!("expected variant, found {}", self.node_to_string(id)),
608         }
609     }
610
611     pub fn expect_foreign_item(&self, id: NodeId) -> &'ast ForeignItem {
612         match self.find(id) {
613             Some(NodeForeignItem(item)) => item,
614             _ => bug!("expected foreign item, found {}", self.node_to_string(id))
615         }
616     }
617
618     pub fn expect_expr(&self, id: NodeId) -> &'ast Expr {
619         match self.find(id) { // read recorded by find
620             Some(NodeExpr(expr)) => expr,
621             _ => bug!("expected expr, found {}", self.node_to_string(id))
622         }
623     }
624
625     pub fn expect_inlined_item(&self, id: NodeId) -> &'ast InlinedItem {
626         match self.find_entry(id) {
627             Some(RootInlinedParent(inlined_item)) => inlined_item,
628             _ => bug!("expected inlined item, found {}", self.node_to_string(id)),
629         }
630     }
631
632     /// Returns the name associated with the given NodeId's AST.
633     pub fn name(&self, id: NodeId) -> Name {
634         match self.get(id) {
635             NodeItem(i) => i.name,
636             NodeForeignItem(i) => i.name,
637             NodeImplItem(ii) => ii.name,
638             NodeTraitItem(ti) => ti.name,
639             NodeVariant(v) => v.node.name,
640             NodeLifetime(lt) => lt.name,
641             NodeTyParam(tp) => tp.name,
642             NodeLocal(&Pat { node: PatKind::Binding(_,l,_), .. }) => l.node,
643             NodeStructCtor(_) => self.name(self.get_parent(id)),
644             _ => bug!("no name for {}", self.node_to_string(id))
645         }
646     }
647
648     /// Given a node ID, get a list of attributes associated with the AST
649     /// corresponding to the Node ID
650     pub fn attrs(&self, id: NodeId) -> &'ast [ast::Attribute] {
651         self.read(id); // reveals attributes on the node
652         let attrs = match self.find(id) {
653             Some(NodeItem(i)) => Some(&i.attrs[..]),
654             Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]),
655             Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]),
656             Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]),
657             Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]),
658             Some(NodeExpr(ref e)) => Some(&*e.attrs),
659             Some(NodeStmt(ref s)) => Some(s.node.attrs()),
660             // unit/tuple structs take the attributes straight from
661             // the struct definition.
662             Some(NodeStructCtor(_)) => {
663                 return self.attrs(self.get_parent(id));
664             }
665             _ => None
666         };
667         attrs.unwrap_or(&[])
668     }
669
670     /// Returns an iterator that yields the node id's with paths that
671     /// match `parts`.  (Requires `parts` is non-empty.)
672     ///
673     /// For example, if given `parts` equal to `["bar", "quux"]`, then
674     /// the iterator will produce node id's for items with paths
675     /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
676     /// any other such items it can find in the map.
677     pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String])
678                                  -> NodesMatchingSuffix<'a, 'ast> {
679         NodesMatchingSuffix {
680             map: self,
681             item_name: parts.last().unwrap(),
682             in_which: &parts[..parts.len() - 1],
683             idx: 0,
684         }
685     }
686
687     pub fn opt_span(&self, id: NodeId) -> Option<Span> {
688         let sp = match self.find(id) {
689             Some(NodeItem(item)) => item.span,
690             Some(NodeForeignItem(foreign_item)) => foreign_item.span,
691             Some(NodeTraitItem(trait_method)) => trait_method.span,
692             Some(NodeImplItem(ref impl_item)) => impl_item.span,
693             Some(NodeVariant(variant)) => variant.span,
694             Some(NodeExpr(expr)) => expr.span,
695             Some(NodeStmt(stmt)) => stmt.span,
696             Some(NodeTy(ty)) => ty.span,
697             Some(NodeLocal(pat)) => pat.span,
698             Some(NodePat(pat)) => pat.span,
699             Some(NodeBlock(block)) => block.span,
700             Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
701             Some(NodeTyParam(ty_param)) => ty_param.span,
702             _ => return None,
703         };
704         Some(sp)
705     }
706
707     pub fn span(&self, id: NodeId) -> Span {
708         self.read(id); // reveals span from node
709         self.opt_span(id)
710             .unwrap_or_else(|| bug!("AstMap.span: could not find span for id {:?}", id))
711     }
712
713     pub fn span_if_local(&self, id: DefId) -> Option<Span> {
714         self.as_local_node_id(id).map(|id| self.span(id))
715     }
716
717     pub fn def_id_span(&self, def_id: DefId, fallback: Span) -> Span {
718         if let Some(node_id) = self.as_local_node_id(def_id) {
719             self.opt_span(node_id).unwrap_or(fallback)
720         } else {
721             fallback
722         }
723     }
724
725     pub fn node_to_string(&self, id: NodeId) -> String {
726         node_id_to_string(self, id, true)
727     }
728
729     pub fn node_to_user_string(&self, id: NodeId) -> String {
730         node_id_to_string(self, id, false)
731     }
732 }
733
734 pub struct NodesMatchingSuffix<'a, 'ast:'a> {
735     map: &'a Map<'ast>,
736     item_name: &'a String,
737     in_which: &'a [String],
738     idx: NodeId,
739 }
740
741 impl<'a, 'ast> NodesMatchingSuffix<'a, 'ast> {
742     /// Returns true only if some suffix of the module path for parent
743     /// matches `self.in_which`.
744     ///
745     /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`;
746     /// returns true if parent's path ends with the suffix
747     /// `x_0::x_1::...::x_k`.
748     fn suffix_matches(&self, parent: NodeId) -> bool {
749         let mut cursor = parent;
750         for part in self.in_which.iter().rev() {
751             let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) {
752                 None => return false,
753                 Some((node_id, name)) => (node_id, name),
754             };
755             if &part[..] != mod_name.as_str() {
756                 return false;
757             }
758             cursor = self.map.get_parent(mod_id);
759         }
760         return true;
761
762         // Finds the first mod in parent chain for `id`, along with
763         // that mod's name.
764         //
765         // If `id` itself is a mod named `m` with parent `p`, then
766         // returns `Some(id, m, p)`.  If `id` has no mod in its parent
767         // chain, then returns `None`.
768         fn find_first_mod_parent<'a>(map: &'a Map, mut id: NodeId) -> Option<(NodeId, Name)> {
769             loop {
770                 match map.find(id) {
771                     None => return None,
772                     Some(NodeItem(item)) if item_is_mod(&item) =>
773                         return Some((id, item.name)),
774                     _ => {}
775                 }
776                 let parent = map.get_parent(id);
777                 if parent == id { return None }
778                 id = parent;
779             }
780
781             fn item_is_mod(item: &Item) -> bool {
782                 match item.node {
783                     ItemMod(_) => true,
784                     _ => false,
785                 }
786             }
787         }
788     }
789
790     // We are looking at some node `n` with a given name and parent
791     // id; do their names match what I am seeking?
792     fn matches_names(&self, parent_of_n: NodeId, name: Name) -> bool {
793         name.as_str() == &self.item_name[..] &&
794             self.suffix_matches(parent_of_n)
795     }
796 }
797
798 impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> {
799     type Item = NodeId;
800
801     fn next(&mut self) -> Option<NodeId> {
802         loop {
803             let idx = self.idx;
804             if idx as usize >= self.map.entry_count() {
805                 return None;
806             }
807             self.idx += 1;
808             let name = match self.map.find_entry(idx) {
809                 Some(EntryItem(_, n))       => n.name(),
810                 Some(EntryForeignItem(_, n))=> n.name(),
811                 Some(EntryTraitItem(_, n))  => n.name(),
812                 Some(EntryImplItem(_, n))   => n.name(),
813                 Some(EntryVariant(_, n))    => n.name(),
814                 _ => continue,
815             };
816             if self.matches_names(self.map.get_parent(idx), name) {
817                 return Some(idx)
818             }
819         }
820     }
821 }
822
823 trait Named {
824     fn name(&self) -> Name;
825 }
826
827 impl<T:Named> Named for Spanned<T> { fn name(&self) -> Name { self.node.name() } }
828
829 impl Named for Item { fn name(&self) -> Name { self.name } }
830 impl Named for ForeignItem { fn name(&self) -> Name { self.name } }
831 impl Named for Variant_ { fn name(&self) -> Name { self.name } }
832 impl Named for TraitItem { fn name(&self) -> Name { self.name } }
833 impl Named for ImplItem { fn name(&self) -> Name { self.name } }
834
835 pub trait FoldOps {
836     fn new_id(&self, id: NodeId) -> NodeId {
837         id
838     }
839     fn new_def_id(&self, def_id: DefId) -> DefId {
840         def_id
841     }
842     fn new_span(&self, span: Span) -> Span {
843         span
844     }
845 }
846
847 /// A Folder that updates IDs and Span's according to fold_ops.
848 pub struct IdAndSpanUpdater<F> {
849     fold_ops: F,
850     min_id_assigned: NodeId,
851     max_id_assigned: NodeId,
852 }
853
854 impl<F: FoldOps> IdAndSpanUpdater<F> {
855     pub fn new(fold_ops: F) -> IdAndSpanUpdater<F> {
856         IdAndSpanUpdater {
857             fold_ops: fold_ops,
858             min_id_assigned: ::std::u32::MAX,
859             max_id_assigned: ::std::u32::MIN,
860         }
861     }
862
863     pub fn id_range(&self) -> intravisit::IdRange {
864         intravisit::IdRange {
865             min: self.min_id_assigned,
866             max: self.max_id_assigned + 1,
867         }
868     }
869 }
870
871 impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
872     fn new_id(&mut self, id: NodeId) -> NodeId {
873         let id = self.fold_ops.new_id(id);
874
875         self.min_id_assigned = cmp::min(self.min_id_assigned, id);
876         self.max_id_assigned = cmp::max(self.max_id_assigned, id);
877
878         id
879     }
880
881     fn new_span(&mut self, span: Span) -> Span {
882         self.fold_ops.new_span(span)
883     }
884 }
885
886 pub fn map_crate<'ast>(forest: &'ast mut Forest,
887                        definitions: Definitions)
888                        -> Map<'ast> {
889     let mut collector = NodeCollector::root(&forest.krate);
890     intravisit::walk_crate(&mut collector, &forest.krate);
891     let map = collector.map;
892
893     if log_enabled!(::log::DEBUG) {
894         // This only makes sense for ordered stores; note the
895         // enumerate to count the number of entries.
896         let (entries_less_1, _) = map.iter().filter(|&x| {
897             match *x {
898                 NotPresent => false,
899                 _ => true
900             }
901         }).enumerate().last().expect("AST map was empty after folding?");
902
903         let entries = entries_less_1 + 1;
904         let vector_length = map.len();
905         debug!("The AST map has {} entries with a maximum of {}: occupancy {:.1}%",
906               entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
907     }
908
909     let local_node_id_watermark = map.len() as NodeId;
910     let local_def_id_watermark = definitions.len();
911
912     Map {
913         forest: forest,
914         dep_graph: forest.dep_graph.clone(),
915         map: RefCell::new(map),
916         definitions: RefCell::new(definitions),
917         local_node_id_watermark: local_node_id_watermark,
918         local_def_id_watermark: local_def_id_watermark,
919     }
920 }
921
922 /// Used for items loaded from external crate that are being inlined into this
923 /// crate.
924 pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
925                                           parent_def_path: DefPath,
926                                           parent_def_id: DefId,
927                                           ii: InlinedItem,
928                                           fold_ops: F)
929                                           -> &'ast InlinedItem {
930     let mut fld = IdAndSpanUpdater::new(fold_ops);
931     let ii = match ii {
932         II::Item(d, i) => II::Item(fld.fold_ops.new_def_id(d),
933                                    i.map(|i| fld.fold_item(i))),
934         II::TraitItem(d, ti) => {
935             II::TraitItem(fld.fold_ops.new_def_id(d),
936                           ti.map(|ti| fld.fold_trait_item(ti)))
937         }
938         II::ImplItem(d, ii) => {
939             II::ImplItem(fld.fold_ops.new_def_id(d),
940                          ii.map(|ii| fld.fold_impl_item(ii)))
941         }
942     };
943
944     let ii = map.forest.inlined_items.alloc(ii);
945     let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
946
947     // Assert that the ii_parent_id is the last NodeId in our reserved range
948     assert!(ii_parent_id == fld.max_id_assigned);
949     // Assert that we did not violate the invariant that all inlined HIR items
950     // have NodeIds greater than or equal to `local_node_id_watermark`
951     assert!(fld.min_id_assigned >= map.local_node_id_watermark);
952
953     let defs = &mut *map.definitions.borrow_mut();
954     let mut def_collector = DefCollector::extend(ii_parent_id,
955                                                  parent_def_path.clone(),
956                                                  parent_def_id,
957                                                  defs);
958     def_collector.walk_item(ii, map.krate());
959
960     let mut collector = NodeCollector::extend(map.krate(),
961                                               ii,
962                                               ii_parent_id,
963                                               parent_def_path,
964                                               parent_def_id,
965                                               mem::replace(&mut *map.map.borrow_mut(), vec![]));
966     ii.visit(&mut collector);
967     *map.map.borrow_mut() = collector.map;
968
969     ii
970 }
971
972 pub trait NodePrinter {
973     fn print_node(&mut self, node: &Node) -> io::Result<()>;
974 }
975
976 impl<'a> NodePrinter for pprust::State<'a> {
977     fn print_node(&mut self, node: &Node) -> io::Result<()> {
978         match *node {
979             NodeItem(a)        => self.print_item(&a),
980             NodeForeignItem(a) => self.print_foreign_item(&a),
981             NodeTraitItem(a)   => self.print_trait_item(a),
982             NodeImplItem(a)    => self.print_impl_item(a),
983             NodeVariant(a)     => self.print_variant(&a),
984             NodeExpr(a)        => self.print_expr(&a),
985             NodeStmt(a)        => self.print_stmt(&a),
986             NodeTy(a)          => self.print_type(&a),
987             NodePat(a)         => self.print_pat(&a),
988             NodeBlock(a)       => self.print_block(&a),
989             NodeLifetime(a)    => self.print_lifetime(&a),
990             NodeTyParam(_)     => bug!("cannot print TyParam"),
991             // these cases do not carry enough information in the
992             // ast_map to reconstruct their full structure for pretty
993             // printing.
994             NodeLocal(_)       => bug!("cannot print isolated Local"),
995             NodeStructCtor(_)  => bug!("cannot print isolated StructCtor"),
996         }
997     }
998 }
999
1000 fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
1001     let id_str = format!(" (id={})", id);
1002     let id_str = if include_id { &id_str[..] } else { "" };
1003
1004     let path_str = || {
1005         // This functionality is used for debugging, try to use TyCtxt to get
1006         // the user-friendly path, otherwise fall back to stringifying DefPath.
1007         ::ty::tls::with_opt(|tcx| {
1008             if let Some(tcx) = tcx {
1009                 tcx.node_path_str(id)
1010             } else if let Some(path) = map.def_path_from_id(id) {
1011                 path.data.into_iter().map(|elem| {
1012                     elem.data.to_string()
1013                 }).collect::<Vec<_>>().join("::")
1014             } else {
1015                 String::from("<missing path>")
1016             }
1017         })
1018     };
1019
1020     match map.find(id) {
1021         Some(NodeItem(item)) => {
1022             let item_str = match item.node {
1023                 ItemExternCrate(..) => "extern crate",
1024                 ItemUse(..) => "use",
1025                 ItemStatic(..) => "static",
1026                 ItemConst(..) => "const",
1027                 ItemFn(..) => "fn",
1028                 ItemMod(..) => "mod",
1029                 ItemForeignMod(..) => "foreign mod",
1030                 ItemTy(..) => "ty",
1031                 ItemEnum(..) => "enum",
1032                 ItemStruct(..) => "struct",
1033                 ItemTrait(..) => "trait",
1034                 ItemImpl(..) => "impl",
1035                 ItemDefaultImpl(..) => "default impl",
1036             };
1037             format!("{} {}{}", item_str, path_str(), id_str)
1038         }
1039         Some(NodeForeignItem(_)) => {
1040             format!("foreign item {}{}", path_str(), id_str)
1041         }
1042         Some(NodeImplItem(ii)) => {
1043             match ii.node {
1044                 ImplItemKind::Const(..) => {
1045                     format!("assoc const {} in {}{}", ii.name, path_str(), id_str)
1046                 }
1047                 ImplItemKind::Method(..) => {
1048                     format!("method {} in {}{}", ii.name, path_str(), id_str)
1049                 }
1050                 ImplItemKind::Type(_) => {
1051                     format!("assoc type {} in {}{}", ii.name, path_str(), id_str)
1052                 }
1053             }
1054         }
1055         Some(NodeTraitItem(ti)) => {
1056             let kind = match ti.node {
1057                 ConstTraitItem(..) => "assoc constant",
1058                 MethodTraitItem(..) => "trait method",
1059                 TypeTraitItem(..) => "assoc type",
1060             };
1061
1062             format!("{} {} in {}{}", kind, ti.name, path_str(), id_str)
1063         }
1064         Some(NodeVariant(ref variant)) => {
1065             format!("variant {} in {}{}",
1066                     variant.node.name,
1067                     path_str(), id_str)
1068         }
1069         Some(NodeExpr(ref expr)) => {
1070             format!("expr {}{}", pprust::expr_to_string(&expr), id_str)
1071         }
1072         Some(NodeStmt(ref stmt)) => {
1073             format!("stmt {}{}", pprust::stmt_to_string(&stmt), id_str)
1074         }
1075         Some(NodeTy(ref ty)) => {
1076             format!("type {}{}", pprust::ty_to_string(&ty), id_str)
1077         }
1078         Some(NodeLocal(ref pat)) => {
1079             format!("local {}{}", pprust::pat_to_string(&pat), id_str)
1080         }
1081         Some(NodePat(ref pat)) => {
1082             format!("pat {}{}", pprust::pat_to_string(&pat), id_str)
1083         }
1084         Some(NodeBlock(ref block)) => {
1085             format!("block {}{}", pprust::block_to_string(&block), id_str)
1086         }
1087         Some(NodeStructCtor(_)) => {
1088             format!("struct_ctor {}{}", path_str(), id_str)
1089         }
1090         Some(NodeLifetime(ref l)) => {
1091             format!("lifetime {}{}",
1092                     pprust::lifetime_to_string(&l), id_str)
1093         }
1094         Some(NodeTyParam(ref ty_param)) => {
1095             format!("typaram {:?}{}", ty_param, id_str)
1096         }
1097         None => {
1098             format!("unknown node{}", id_str)
1099         }
1100     }
1101 }