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.
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.
11 pub use self::Node
::*;
12 use self::MapEntry
::*;
13 use self::collector
::NodeCollector
;
14 pub use self::definitions
::{Definitions
, DefKey
, DefPath
, DefPathData
,
15 DisambiguatedDefPathData
, InlinedRootPath
};
17 use dep_graph
::{DepGraph, DepNode}
;
19 use middle
::cstore
::InlinedItem
;
20 use middle
::cstore
::InlinedItem
as II
;
21 use hir
::def_id
::{CRATE_DEF_INDEX, DefId}
;
24 use syntax
::ast
::{self, Name, NodeId, DUMMY_NODE_ID}
;
25 use syntax
::attr
::ThinAttributesExt
;
26 use syntax
::codemap
::{Span, Spanned}
;
29 use hir
::fold
::Folder
;
30 use hir
::print
as pprust
;
32 use arena
::TypedArena
;
33 use std
::cell
::RefCell
;
41 #[derive(Copy, Clone, Debug)]
44 NodeForeignItem(&'ast ForeignItem
),
45 NodeTraitItem(&'ast TraitItem
),
46 NodeImplItem(&'ast ImplItem
),
47 NodeVariant(&'ast Variant
),
52 NodeBlock(&'ast Block
),
54 /// NodeStructCtor represents a tuple struct.
55 NodeStructCtor(&'ast VariantData
),
57 NodeLifetime(&'ast Lifetime
),
58 NodeTyParam(&'ast TyParam
)
61 /// Represents an entry and its parent NodeID.
62 /// The odd layout is to bring down the total size.
63 #[derive(Copy, Debug)]
64 pub enum MapEntry
<'ast
> {
65 /// Placeholder for holes in the map.
68 /// All the node types, with a parent ID.
69 EntryItem(NodeId
, &'ast Item
),
70 EntryForeignItem(NodeId
, &'ast ForeignItem
),
71 EntryTraitItem(NodeId
, &'ast TraitItem
),
72 EntryImplItem(NodeId
, &'ast ImplItem
),
73 EntryVariant(NodeId
, &'ast Variant
),
74 EntryExpr(NodeId
, &'ast Expr
),
75 EntryStmt(NodeId
, &'ast Stmt
),
76 EntryLocal(NodeId
, &'ast Pat
),
77 EntryPat(NodeId
, &'ast Pat
),
78 EntryBlock(NodeId
, &'ast Block
),
79 EntryStructCtor(NodeId
, &'ast VariantData
),
80 EntryLifetime(NodeId
, &'ast Lifetime
),
81 EntryTyParam(NodeId
, &'ast TyParam
),
83 /// Roots for node trees.
85 RootInlinedParent(&'ast InlinedItem
)
88 impl<'ast
> Clone
for MapEntry
<'ast
> {
89 fn clone(&self) -> MapEntry
<'ast
> {
94 impl<'ast
> MapEntry
<'ast
> {
95 fn from_node(p
: NodeId
, node
: Node
<'ast
>) -> MapEntry
<'ast
> {
97 NodeItem(n
) => EntryItem(p
, n
),
98 NodeForeignItem(n
) => EntryForeignItem(p
, n
),
99 NodeTraitItem(n
) => EntryTraitItem(p
, n
),
100 NodeImplItem(n
) => EntryImplItem(p
, n
),
101 NodeVariant(n
) => EntryVariant(p
, n
),
102 NodeExpr(n
) => EntryExpr(p
, n
),
103 NodeStmt(n
) => EntryStmt(p
, n
),
104 NodeLocal(n
) => EntryLocal(p
, n
),
105 NodePat(n
) => EntryPat(p
, n
),
106 NodeBlock(n
) => EntryBlock(p
, n
),
107 NodeStructCtor(n
) => EntryStructCtor(p
, n
),
108 NodeLifetime(n
) => EntryLifetime(p
, n
),
109 NodeTyParam(n
) => EntryTyParam(p
, n
),
113 fn parent_node(self) -> Option
<NodeId
> {
115 EntryItem(id
, _
) => id
,
116 EntryForeignItem(id
, _
) => id
,
117 EntryTraitItem(id
, _
) => id
,
118 EntryImplItem(id
, _
) => id
,
119 EntryVariant(id
, _
) => id
,
120 EntryExpr(id
, _
) => id
,
121 EntryStmt(id
, _
) => id
,
122 EntryLocal(id
, _
) => id
,
123 EntryPat(id
, _
) => id
,
124 EntryBlock(id
, _
) => id
,
125 EntryStructCtor(id
, _
) => id
,
126 EntryLifetime(id
, _
) => id
,
127 EntryTyParam(id
, _
) => id
,
132 fn to_node(self) -> Option
<Node
<'ast
>> {
134 EntryItem(_
, n
) => NodeItem(n
),
135 EntryForeignItem(_
, n
) => NodeForeignItem(n
),
136 EntryTraitItem(_
, n
) => NodeTraitItem(n
),
137 EntryImplItem(_
, n
) => NodeImplItem(n
),
138 EntryVariant(_
, n
) => NodeVariant(n
),
139 EntryExpr(_
, n
) => NodeExpr(n
),
140 EntryStmt(_
, n
) => NodeStmt(n
),
141 EntryLocal(_
, n
) => NodeLocal(n
),
142 EntryPat(_
, n
) => NodePat(n
),
143 EntryBlock(_
, n
) => NodeBlock(n
),
144 EntryStructCtor(_
, n
) => NodeStructCtor(n
),
145 EntryLifetime(_
, n
) => NodeLifetime(n
),
146 EntryTyParam(_
, n
) => NodeTyParam(n
),
152 /// Stores a crate and any number of inlined items from other crates.
155 pub dep_graph
: DepGraph
,
156 inlined_items
: TypedArena
<InlinedItem
>
160 pub fn new(krate
: Crate
, dep_graph
: DepGraph
) -> Forest
{
163 dep_graph
: dep_graph
,
164 inlined_items
: TypedArena
::new()
168 pub fn krate
<'ast
>(&'ast
self) -> &'ast Crate
{
169 self.dep_graph
.read(DepNode
::Krate
);
174 /// Represents a mapping from Node IDs to AST elements and their parent
177 pub struct Map
<'ast
> {
178 /// The backing storage for all the AST nodes.
179 pub forest
: &'ast Forest
,
181 /// Same as the dep_graph in forest, just available with one fewer
182 /// deref. This is a gratuitious micro-optimization.
183 pub dep_graph
: DepGraph
,
185 /// NodeIds are sequential integers from 0, so we can be
186 /// super-compact by storing them in a vector. Not everything with
187 /// a NodeId is in the map, but empirically the occupancy is about
188 /// 75-80%, so there's not too much overhead (certainly less than
189 /// a hashmap, since they (at the time of writing) have a maximum
190 /// of 75% occupancy).
192 /// Also, indexing is pretty quick when you've got a vector and
193 /// plain old integers.
194 map
: RefCell
<Vec
<MapEntry
<'ast
>>>,
196 definitions
: RefCell
<Definitions
>,
199 impl<'ast
> Map
<'ast
> {
200 /// Registers a read in the dependency graph of the AST node with
201 /// the given `id`. This needs to be called each time a public
202 /// function returns the HIR for a node -- in other words, when it
203 /// "reveals" the content of a node to the caller (who might not
204 /// otherwise have had access to those contents, and hence needs a
205 /// read recorded). If the function just returns a DefId or
206 /// NodeId, no actual content was returned, so no read is needed.
207 fn read(&self, id
: NodeId
) {
208 self.dep_graph
.read(self.dep_node(id
));
211 fn dep_node(&self, id0
: NodeId
) -> DepNode
<DefId
> {
212 let map
= self.map
.borrow();
215 match map
[id
as usize] {
216 EntryItem(_
, item
) => {
217 let def_id
= self.local_def_id(item
.id
);
220 // You would expect that `item.id == id`, but this
221 // is not always the case. In particular, for a
222 // ViewPath item like `use self::{mem, foo}`, we
223 // map the ids for `mem` and `foo` to the
224 // enclosing view path item. This seems mega super
225 // ultra wrong, but then who am I to judge?
227 return DepNode
::Hir(def_id
);
230 EntryForeignItem(p
, _
) |
231 EntryTraitItem(p
, _
) |
232 EntryImplItem(p
, _
) |
239 EntryStructCtor(p
, _
) |
240 EntryLifetime(p
, _
) |
241 EntryTyParam(p
, _
) =>
245 RootInlinedParent(_
) =>
246 // FIXME(#32015) clarify story about cross-crate dep tracking
247 return DepNode
::Krate
,
250 // Some nodes, notably struct fields, are not
251 // present in the map for whatever reason, but
252 // they *do* have def-ids. So if we encounter an
253 // empty hole, check for that case.
254 return self.opt_local_def_id(id
)
255 .map(|def_id
| DepNode
::Hir(def_id
))
257 bug
!("Walking parents from `{}` \
258 led to `NotPresent` at `{}`",
265 pub fn num_local_def_ids(&self) -> usize {
266 self.definitions
.borrow().len()
269 pub fn def_key(&self, def_id
: DefId
) -> DefKey
{
270 assert
!(def_id
.is_local());
271 self.definitions
.borrow().def_key(def_id
.index
)
274 pub fn def_path_from_id(&self, id
: NodeId
) -> Option
<DefPath
> {
275 self.opt_local_def_id(id
).map(|def_id
| {
276 self.def_path(def_id
)
280 pub fn def_path(&self, def_id
: DefId
) -> DefPath
{
281 assert
!(def_id
.is_local());
282 self.definitions
.borrow().def_path(def_id
.index
)
285 pub fn retrace_path(&self, path
: &DefPath
) -> Option
<DefId
> {
286 self.definitions
.borrow().retrace_path(path
)
290 pub fn local_def_id(&self, node
: NodeId
) -> DefId
{
291 self.opt_local_def_id(node
).unwrap_or_else(|| {
292 bug
!("local_def_id: no entry for `{}`, which has a map of `{:?}`",
293 node
, self.find_entry(node
))
297 pub fn opt_local_def_id(&self, node
: NodeId
) -> Option
<DefId
> {
298 self.definitions
.borrow().opt_local_def_id(node
)
301 pub fn as_local_node_id(&self, def_id
: DefId
) -> Option
<NodeId
> {
302 self.definitions
.borrow().as_local_node_id(def_id
)
305 fn entry_count(&self) -> usize {
306 self.map
.borrow().len()
309 fn find_entry(&self, id
: NodeId
) -> Option
<MapEntry
<'ast
>> {
310 self.map
.borrow().get(id
as usize).cloned()
313 pub fn krate(&self) -> &'ast Crate
{
317 /// Get the attributes on the krate. This is preferable to
318 /// invoking `krate.attrs` because it registers a tighter
319 /// dep-graph access.
320 pub fn krate_attrs(&self) -> &'ast
[ast
::Attribute
] {
321 let crate_root_def_id
= DefId
::local(CRATE_DEF_INDEX
);
322 self.dep_graph
.read(DepNode
::Hir(crate_root_def_id
));
323 &self.forest
.krate
.attrs
326 /// Retrieve the Node corresponding to `id`, panicking if it cannot
328 pub fn get(&self, id
: NodeId
) -> Node
<'ast
> {
329 match self.find(id
) {
330 Some(node
) => node
, // read recorded by `find`
331 None
=> bug
!("couldn't find node id {} in the AST map", id
)
335 pub fn get_if_local(&self, id
: DefId
) -> Option
<Node
<'ast
>> {
336 self.as_local_node_id(id
).map(|id
| self.get(id
)) // read recorded by `get`
339 /// Retrieve the Node corresponding to `id`, returning None if
341 pub fn find(&self, id
: NodeId
) -> Option
<Node
<'ast
>> {
342 let result
= self.find_entry(id
).and_then(|x
| x
.to_node());
343 if result
.is_some() {
349 /// Similar to get_parent, returns the parent node id or id if there is no
351 /// This function returns the immediate parent in the AST, whereas get_parent
352 /// returns the enclosing item. Note that this might not be the actual parent
353 /// node in the AST - some kinds of nodes are not in the map and these will
354 /// never appear as the parent_node. So you can always walk the parent_nodes
355 /// from a node to the root of the ast (unless you get the same id back here
356 /// that can happen if the id is not in the map itself or is just weird).
357 pub fn get_parent_node(&self, id
: NodeId
) -> NodeId
{
358 self.find_entry(id
).and_then(|x
| x
.parent_node()).unwrap_or(id
)
361 /// Check if the node is an argument. An argument is a local variable whose
362 /// immediate parent is an item or a closure.
363 pub fn is_argument(&self, id
: NodeId
) -> bool
{
364 match self.find(id
) {
365 Some(NodeLocal(_
)) => (),
368 match self.find(self.get_parent_node(id
)) {
370 Some(NodeTraitItem(_
)) |
371 Some(NodeImplItem(_
)) => true,
372 Some(NodeExpr(e
)) => {
374 ExprClosure(..) => true,
382 /// If there is some error when walking the parents (e.g., a node does not
383 /// have a parent in the map or a node can't be found), then we return the
384 /// last good node id we found. Note that reaching the crate root (id == 0),
385 /// is not an error, since items in the crate module have the crate root as
387 fn walk_parent_nodes
<F
>(&self, start_id
: NodeId
, found
: F
) -> Result
<NodeId
, NodeId
>
388 where F
: Fn(&Node
<'ast
>) -> bool
390 let mut id
= start_id
;
392 let parent_node
= self.get_parent_node(id
);
393 if parent_node
== 0 {
396 if parent_node
== id
{
400 let node
= self.find_entry(parent_node
);
404 let node
= node
.unwrap().to_node();
408 return Ok(parent_node
);
412 return Err(parent_node
);
419 /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
420 /// parent item is in this map. The "parent item" is the closest parent node
421 /// in the AST which is recorded by the map and is an item, either an item
422 /// in a module, trait, or impl.
423 pub fn get_parent(&self, id
: NodeId
) -> NodeId
{
424 match self.walk_parent_nodes(id
, |node
| match *node
{
428 NodeImplItem(_
) => true,
436 /// Returns the NodeId of `id`'s nearest module parent, or `id` itself if no
437 /// module parent is in this map.
438 pub fn get_module_parent(&self, id
: NodeId
) -> NodeId
{
439 match self.walk_parent_nodes(id
, |node
| match *node
{
440 NodeItem(&Item { node: Item_::ItemMod(_), .. }
) => true,
448 /// Returns the nearest enclosing scope. A scope is an item or block.
449 /// FIXME it is not clear to me that all items qualify as scopes - statics
450 /// and associated types probably shouldn't, for example. Behaviour in this
451 /// regard should be expected to be highly unstable.
452 pub fn get_enclosing_scope(&self, id
: NodeId
) -> Option
<NodeId
> {
453 match self.walk_parent_nodes(id
, |node
| match *node
{
458 NodeBlock(_
) => true,
466 pub fn get_parent_did(&self, id
: NodeId
) -> DefId
{
467 let parent
= self.get_parent(id
);
468 match self.find_entry(parent
) {
469 Some(RootInlinedParent(&II
::TraitItem(did
, _
))) |
470 Some(RootInlinedParent(&II
::ImplItem(did
, _
))) => did
,
471 _
=> self.local_def_id(parent
)
475 pub fn get_foreign_abi(&self, id
: NodeId
) -> Abi
{
476 let parent
= self.get_parent(id
);
477 let abi
= match self.find_entry(parent
) {
478 Some(EntryItem(_
, i
)) => {
480 ItemForeignMod(ref nm
) => Some(nm
.abi
),
484 /// Wrong but OK, because the only inlined foreign items are intrinsics.
485 Some(RootInlinedParent(_
)) => Some(Abi
::RustIntrinsic
),
490 self.read(id
); // reveals some of the content of a node
493 None
=> bug
!("expected foreign mod or inlined parent, found {}",
494 self.node_to_string(parent
))
498 pub fn expect_item(&self, id
: NodeId
) -> &'ast Item
{
499 match self.find(id
) { // read recorded by `find`
500 Some(NodeItem(item
)) => item
,
501 _
=> bug
!("expected item, found {}", self.node_to_string(id
))
505 pub fn expect_trait_item(&self, id
: NodeId
) -> &'ast TraitItem
{
506 match self.find(id
) {
507 Some(NodeTraitItem(item
)) => item
,
508 _
=> bug
!("expected trait item, found {}", self.node_to_string(id
))
512 pub fn expect_struct(&self, id
: NodeId
) -> &'ast VariantData
{
513 match self.find(id
) {
514 Some(NodeItem(i
)) => {
516 ItemStruct(ref struct_def
, _
) => struct_def
,
517 _
=> bug
!("struct ID bound to non-struct")
520 Some(NodeVariant(variant
)) => {
521 if variant
.node
.data
.is_struct() {
524 bug
!("struct ID bound to enum variant that isn't struct-like")
527 _
=> bug
!("expected struct, found {}", self.node_to_string(id
)),
531 pub fn expect_variant(&self, id
: NodeId
) -> &'ast Variant
{
532 match self.find(id
) {
533 Some(NodeVariant(variant
)) => variant
,
534 _
=> bug
!("expected variant, found {}", self.node_to_string(id
)),
538 pub fn expect_foreign_item(&self, id
: NodeId
) -> &'ast ForeignItem
{
539 match self.find(id
) {
540 Some(NodeForeignItem(item
)) => item
,
541 _
=> bug
!("expected foreign item, found {}", self.node_to_string(id
))
545 pub fn expect_expr(&self, id
: NodeId
) -> &'ast Expr
{
546 match self.find(id
) { // read recorded by find
547 Some(NodeExpr(expr
)) => expr
,
548 _
=> bug
!("expected expr, found {}", self.node_to_string(id
))
552 /// Returns the name associated with the given NodeId's AST.
553 pub fn name(&self, id
: NodeId
) -> Name
{
555 NodeItem(i
) => i
.name
,
556 NodeForeignItem(i
) => i
.name
,
557 NodeImplItem(ii
) => ii
.name
,
558 NodeTraitItem(ti
) => ti
.name
,
559 NodeVariant(v
) => v
.node
.name
,
560 NodeLifetime(lt
) => lt
.name
,
561 NodeTyParam(tp
) => tp
.name
,
562 NodeLocal(&Pat { node: PatKind::Ident(_,l,_), .. }
) => {
565 NodeStructCtor(_
) => self.name(self.get_parent(id
)),
566 _
=> bug
!("no name for {}", self.node_to_string(id
))
570 /// Given a node ID, get a list of attributes associated with the AST
571 /// corresponding to the Node ID
572 pub fn attrs(&self, id
: NodeId
) -> &'ast
[ast
::Attribute
] {
573 self.read(id
); // reveals attributes on the node
574 let attrs
= match self.find(id
) {
575 Some(NodeItem(i
)) => Some(&i
.attrs
[..]),
576 Some(NodeForeignItem(fi
)) => Some(&fi
.attrs
[..]),
577 Some(NodeTraitItem(ref ti
)) => Some(&ti
.attrs
[..]),
578 Some(NodeImplItem(ref ii
)) => Some(&ii
.attrs
[..]),
579 Some(NodeVariant(ref v
)) => Some(&v
.node
.attrs
[..]),
580 Some(NodeExpr(ref e
)) => Some(e
.attrs
.as_attr_slice()),
581 Some(NodeStmt(ref s
)) => Some(s
.node
.attrs()),
582 // unit/tuple structs take the attributes straight from
583 // the struct definition.
584 Some(NodeStructCtor(_
)) => {
585 return self.attrs(self.get_parent(id
));
592 /// Returns an iterator that yields the node id's with paths that
593 /// match `parts`. (Requires `parts` is non-empty.)
595 /// For example, if given `parts` equal to `["bar", "quux"]`, then
596 /// the iterator will produce node id's for items with paths
597 /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
598 /// any other such items it can find in the map.
599 pub fn nodes_matching_suffix
<'a
>(&'a
self, parts
: &'a
[String
])
600 -> NodesMatchingSuffix
<'a
, 'ast
> {
601 NodesMatchingSuffix
{
603 item_name
: parts
.last().unwrap(),
604 in_which
: &parts
[..parts
.len() - 1],
609 pub fn opt_span(&self, id
: NodeId
) -> Option
<Span
> {
610 let sp
= match self.find(id
) {
611 Some(NodeItem(item
)) => item
.span
,
612 Some(NodeForeignItem(foreign_item
)) => foreign_item
.span
,
613 Some(NodeTraitItem(trait_method
)) => trait_method
.span
,
614 Some(NodeImplItem(ref impl_item
)) => impl_item
.span
,
615 Some(NodeVariant(variant
)) => variant
.span
,
616 Some(NodeExpr(expr
)) => expr
.span
,
617 Some(NodeStmt(stmt
)) => stmt
.span
,
618 Some(NodeLocal(pat
)) => pat
.span
,
619 Some(NodePat(pat
)) => pat
.span
,
620 Some(NodeBlock(block
)) => block
.span
,
621 Some(NodeStructCtor(_
)) => self.expect_item(self.get_parent(id
)).span
,
622 Some(NodeTyParam(ty_param
)) => ty_param
.span
,
628 pub fn span(&self, id
: NodeId
) -> Span
{
629 self.read(id
); // reveals span from node
631 .unwrap_or_else(|| bug
!("AstMap.span: could not find span for id {:?}", id
))
634 pub fn span_if_local(&self, id
: DefId
) -> Option
<Span
> {
635 self.as_local_node_id(id
).map(|id
| self.span(id
))
638 pub fn def_id_span(&self, def_id
: DefId
, fallback
: Span
) -> Span
{
639 if let Some(node_id
) = self.as_local_node_id(def_id
) {
640 self.opt_span(node_id
).unwrap_or(fallback
)
646 pub fn node_to_string(&self, id
: NodeId
) -> String
{
647 node_id_to_string(self, id
, true)
650 pub fn node_to_user_string(&self, id
: NodeId
) -> String
{
651 node_id_to_string(self, id
, false)
655 pub struct NodesMatchingSuffix
<'a
, 'ast
:'a
> {
657 item_name
: &'a String
,
658 in_which
: &'a
[String
],
662 impl<'a
, 'ast
> NodesMatchingSuffix
<'a
, 'ast
> {
663 /// Returns true only if some suffix of the module path for parent
664 /// matches `self.in_which`.
666 /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`;
667 /// returns true if parent's path ends with the suffix
668 /// `x_0::x_1::...::x_k`.
669 fn suffix_matches(&self, parent
: NodeId
) -> bool
{
670 let mut cursor
= parent
;
671 for part
in self.in_which
.iter().rev() {
672 let (mod_id
, mod_name
) = match find_first_mod_parent(self.map
, cursor
) {
673 None
=> return false,
674 Some((node_id
, name
)) => (node_id
, name
),
676 if &part
[..] != mod_name
.as_str() {
679 cursor
= self.map
.get_parent(mod_id
);
683 // Finds the first mod in parent chain for `id`, along with
686 // If `id` itself is a mod named `m` with parent `p`, then
687 // returns `Some(id, m, p)`. If `id` has no mod in its parent
688 // chain, then returns `None`.
689 fn find_first_mod_parent
<'a
>(map
: &'a Map
, mut id
: NodeId
) -> Option
<(NodeId
, Name
)> {
693 Some(NodeItem(item
)) if item_is_mod(&item
) =>
694 return Some((id
, item
.name
)),
697 let parent
= map
.get_parent(id
);
698 if parent
== id { return None }
702 fn item_is_mod(item
: &Item
) -> bool
{
711 // We are looking at some node `n` with a given name and parent
712 // id; do their names match what I am seeking?
713 fn matches_names(&self, parent_of_n
: NodeId
, name
: Name
) -> bool
{
714 name
.as_str() == &self.item_name
[..] &&
715 self.suffix_matches(parent_of_n
)
719 impl<'a
, 'ast
> Iterator
for NodesMatchingSuffix
<'a
, 'ast
> {
722 fn next(&mut self) -> Option
<NodeId
> {
725 if idx
as usize >= self.map
.entry_count() {
729 let name
= match self.map
.find_entry(idx
) {
730 Some(EntryItem(_
, n
)) => n
.name(),
731 Some(EntryForeignItem(_
, n
))=> n
.name(),
732 Some(EntryTraitItem(_
, n
)) => n
.name(),
733 Some(EntryImplItem(_
, n
)) => n
.name(),
734 Some(EntryVariant(_
, n
)) => n
.name(),
737 if self.matches_names(self.map
.get_parent(idx
), name
) {
745 fn name(&self) -> Name
;
748 impl<T
:Named
> Named
for Spanned
<T
> { fn name(&self) -> Name { self.node.name() }
}
750 impl Named
for Item { fn name(&self) -> Name { self.name }
}
751 impl Named
for ForeignItem { fn name(&self) -> Name { self.name }
}
752 impl Named
for Variant_ { fn name(&self) -> Name { self.name }
}
753 impl Named
for TraitItem { fn name(&self) -> Name { self.name }
}
754 impl Named
for ImplItem { fn name(&self) -> Name { self.name }
}
757 fn new_id(&self, id
: NodeId
) -> NodeId
{
760 fn new_def_id(&self, def_id
: DefId
) -> DefId
{
763 fn new_span(&self, span
: Span
) -> Span
{
768 /// A Folder that updates IDs and Span's according to fold_ops.
769 struct IdAndSpanUpdater
<F
> {
773 impl<F
: FoldOps
> Folder
for IdAndSpanUpdater
<F
> {
774 fn new_id(&mut self, id
: NodeId
) -> NodeId
{
775 self.fold_ops
.new_id(id
)
778 fn new_span(&mut self, span
: Span
) -> Span
{
779 self.fold_ops
.new_span(span
)
783 pub fn map_crate
<'ast
>(forest
: &'ast
mut Forest
) -> Map
<'ast
> {
784 let (map
, definitions
) = {
785 let mut collector
= NodeCollector
::root(&forest
.krate
);
786 intravisit
::walk_crate(&mut collector
, &forest
.krate
);
787 (collector
.map
, collector
.definitions
)
790 if log_enabled
!(::log
::DEBUG
) {
791 // This only makes sense for ordered stores; note the
792 // enumerate to count the number of entries.
793 let (entries_less_1
, _
) = map
.iter().filter(|&x
| {
798 }).enumerate().last().expect("AST map was empty after folding?");
800 let entries
= entries_less_1
+ 1;
801 let vector_length
= map
.len();
802 debug
!("The AST map has {} entries with a maximum of {}: occupancy {:.1}%",
803 entries
, vector_length
, (entries
as f64 / vector_length
as f64) * 100.);
808 dep_graph
: forest
.dep_graph
.clone(),
809 map
: RefCell
::new(map
),
810 definitions
: RefCell
::new(definitions
),
814 /// Used for items loaded from external crate that are being inlined into this
816 pub fn map_decoded_item
<'ast
, F
: FoldOps
>(map
: &Map
<'ast
>,
817 parent_def_path
: DefPath
,
818 parent_def_id
: DefId
,
821 -> &'ast InlinedItem
{
822 let mut fld
= IdAndSpanUpdater { fold_ops: fold_ops }
;
824 II
::Item(i
) => II
::Item(i
.map(|i
| fld
.fold_item(i
))),
825 II
::TraitItem(d
, ti
) => {
826 II
::TraitItem(fld
.fold_ops
.new_def_id(d
),
827 ti
.map(|ti
| fld
.fold_trait_item(ti
)))
829 II
::ImplItem(d
, ii
) => {
830 II
::ImplItem(fld
.fold_ops
.new_def_id(d
),
831 ii
.map(|ii
| fld
.fold_impl_item(ii
)))
833 II
::Foreign(i
) => II
::Foreign(i
.map(|i
| fld
.fold_foreign_item(i
)))
836 let ii
= map
.forest
.inlined_items
.alloc(ii
);
838 let ii_parent_id
= fld
.new_id(DUMMY_NODE_ID
);
840 NodeCollector
::extend(
846 mem
::replace(&mut *map
.map
.borrow_mut(), vec
![]),
847 mem
::replace(&mut *map
.definitions
.borrow_mut(), Definitions
::new()));
848 ii
.visit(&mut collector
);
850 *map
.map
.borrow_mut() = collector
.map
;
851 *map
.definitions
.borrow_mut() = collector
.definitions
;
856 pub trait NodePrinter
{
857 fn print_node(&mut self, node
: &Node
) -> io
::Result
<()>;
860 impl<'a
> NodePrinter
for pprust
::State
<'a
> {
861 fn print_node(&mut self, node
: &Node
) -> io
::Result
<()> {
863 NodeItem(a
) => self.print_item(&a
),
864 NodeForeignItem(a
) => self.print_foreign_item(&a
),
865 NodeTraitItem(a
) => self.print_trait_item(a
),
866 NodeImplItem(a
) => self.print_impl_item(a
),
867 NodeVariant(a
) => self.print_variant(&a
),
868 NodeExpr(a
) => self.print_expr(&a
),
869 NodeStmt(a
) => self.print_stmt(&a
),
870 NodePat(a
) => self.print_pat(&a
),
871 NodeBlock(a
) => self.print_block(&a
),
872 NodeLifetime(a
) => self.print_lifetime(&a
),
873 NodeTyParam(_
) => bug
!("cannot print TyParam"),
874 // these cases do not carry enough information in the
875 // ast_map to reconstruct their full structure for pretty
877 NodeLocal(_
) => bug
!("cannot print isolated Local"),
878 NodeStructCtor(_
) => bug
!("cannot print isolated StructCtor"),
883 fn node_id_to_string(map
: &Map
, id
: NodeId
, include_id
: bool
) -> String
{
884 let id_str
= format
!(" (id={})", id
);
885 let id_str
= if include_id { &id_str[..] }
else { "" }
;
888 // This functionality is used for debugging, try to use TyCtxt to get
889 // the user-friendly path, otherwise fall back to stringifying DefPath.
890 ::ty
::tls
::with_opt(|tcx
| {
891 if let Some(tcx
) = tcx
{
892 tcx
.node_path_str(id
)
893 } else if let Some(path
) = map
.def_path_from_id(id
) {
894 path
.data
.into_iter().map(|elem
| {
895 elem
.data
.to_string()
896 }).collect
::<Vec
<_
>>().join("::")
898 String
::from("<missing path>")
904 Some(NodeItem(item
)) => {
905 let item_str
= match item
.node
{
906 ItemExternCrate(..) => "extern crate",
907 ItemUse(..) => "use",
908 ItemStatic(..) => "static",
909 ItemConst(..) => "const",
911 ItemMod(..) => "mod",
912 ItemForeignMod(..) => "foreign mod",
914 ItemEnum(..) => "enum",
915 ItemStruct(..) => "struct",
916 ItemTrait(..) => "trait",
917 ItemImpl(..) => "impl",
918 ItemDefaultImpl(..) => "default impl",
920 format
!("{} {}{}", item_str
, path_str(), id_str
)
922 Some(NodeForeignItem(_
)) => {
923 format
!("foreign item {}{}", path_str(), id_str
)
925 Some(NodeImplItem(ii
)) => {
927 ImplItemKind
::Const(..) => {
928 format
!("assoc const {} in {}{}", ii
.name
, path_str(), id_str
)
930 ImplItemKind
::Method(..) => {
931 format
!("method {} in {}{}", ii
.name
, path_str(), id_str
)
933 ImplItemKind
::Type(_
) => {
934 format
!("assoc type {} in {}{}", ii
.name
, path_str(), id_str
)
938 Some(NodeTraitItem(ti
)) => {
939 let kind
= match ti
.node
{
940 ConstTraitItem(..) => "assoc constant",
941 MethodTraitItem(..) => "trait method",
942 TypeTraitItem(..) => "assoc type",
945 format
!("{} {} in {}{}", kind
, ti
.name
, path_str(), id_str
)
947 Some(NodeVariant(ref variant
)) => {
948 format
!("variant {} in {}{}",
952 Some(NodeExpr(ref expr
)) => {
953 format
!("expr {}{}", pprust
::expr_to_string(&expr
), id_str
)
955 Some(NodeStmt(ref stmt
)) => {
956 format
!("stmt {}{}", pprust
::stmt_to_string(&stmt
), id_str
)
958 Some(NodeLocal(ref pat
)) => {
959 format
!("local {}{}", pprust
::pat_to_string(&pat
), id_str
)
961 Some(NodePat(ref pat
)) => {
962 format
!("pat {}{}", pprust
::pat_to_string(&pat
), id_str
)
964 Some(NodeBlock(ref block
)) => {
965 format
!("block {}{}", pprust
::block_to_string(&block
), id_str
)
967 Some(NodeStructCtor(_
)) => {
968 format
!("struct_ctor {}{}", path_str(), id_str
)
970 Some(NodeLifetime(ref l
)) => {
971 format
!("lifetime {}{}",
972 pprust
::lifetime_to_string(&l
), id_str
)
974 Some(NodeTyParam(ref ty_param
)) => {
975 format
!("typaram {:?}{}", ty_param
, id_str
)
978 format
!("unknown node{}", id_str
)