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::def_collector
::{DefCollector, MacroInvocationData}
;
15 pub use self::definitions
::{Definitions
, DefKey
, DefPath
, DefPathData
,
16 DisambiguatedDefPathData
, InlinedRootPath
};
18 use dep_graph
::{DepGraph, DepNode}
;
20 use middle
::cstore
::InlinedItem
;
21 use middle
::cstore
::InlinedItem
as II
;
22 use hir
::def_id
::{CRATE_DEF_INDEX, DefId, DefIndex}
;
25 use syntax
::ast
::{self, Name, NodeId, CRATE_NODE_ID}
;
26 use syntax
::codemap
::Spanned
;
30 use hir
::print
as pprust
;
32 use arena
::TypedArena
;
33 use std
::cell
::RefCell
;
42 #[derive(Copy, Clone, Debug)]
45 NodeForeignItem(&'ast ForeignItem
),
46 NodeTraitItem(&'ast TraitItem
),
47 NodeImplItem(&'ast ImplItem
),
48 NodeVariant(&'ast Variant
),
54 NodeBlock(&'ast Block
),
56 /// NodeStructCtor represents a tuple struct.
57 NodeStructCtor(&'ast VariantData
),
59 NodeLifetime(&'ast Lifetime
),
60 NodeTyParam(&'ast TyParam
)
63 /// Represents an entry and its parent NodeID.
64 /// The odd layout is to bring down the total size.
65 #[derive(Copy, Debug)]
66 pub enum MapEntry
<'ast
> {
67 /// Placeholder for holes in the map.
70 /// All the node types, with a parent ID.
71 EntryItem(NodeId
, &'ast Item
),
72 EntryForeignItem(NodeId
, &'ast ForeignItem
),
73 EntryTraitItem(NodeId
, &'ast TraitItem
),
74 EntryImplItem(NodeId
, &'ast ImplItem
),
75 EntryVariant(NodeId
, &'ast Variant
),
76 EntryExpr(NodeId
, &'ast Expr
),
77 EntryStmt(NodeId
, &'ast Stmt
),
78 EntryTy(NodeId
, &'ast Ty
),
79 EntryLocal(NodeId
, &'ast Pat
),
80 EntryPat(NodeId
, &'ast Pat
),
81 EntryBlock(NodeId
, &'ast Block
),
82 EntryStructCtor(NodeId
, &'ast VariantData
),
83 EntryLifetime(NodeId
, &'ast Lifetime
),
84 EntryTyParam(NodeId
, &'ast TyParam
),
86 /// Roots for node trees.
88 RootInlinedParent(&'ast InlinedItem
)
91 impl<'ast
> Clone
for MapEntry
<'ast
> {
92 fn clone(&self) -> MapEntry
<'ast
> {
97 impl<'ast
> MapEntry
<'ast
> {
98 fn from_node(p
: NodeId
, node
: Node
<'ast
>) -> MapEntry
<'ast
> {
100 NodeItem(n
) => EntryItem(p
, n
),
101 NodeForeignItem(n
) => EntryForeignItem(p
, n
),
102 NodeTraitItem(n
) => EntryTraitItem(p
, n
),
103 NodeImplItem(n
) => EntryImplItem(p
, n
),
104 NodeVariant(n
) => EntryVariant(p
, n
),
105 NodeExpr(n
) => EntryExpr(p
, n
),
106 NodeStmt(n
) => EntryStmt(p
, n
),
107 NodeTy(n
) => EntryTy(p
, n
),
108 NodeLocal(n
) => EntryLocal(p
, n
),
109 NodePat(n
) => EntryPat(p
, n
),
110 NodeBlock(n
) => EntryBlock(p
, n
),
111 NodeStructCtor(n
) => EntryStructCtor(p
, n
),
112 NodeLifetime(n
) => EntryLifetime(p
, n
),
113 NodeTyParam(n
) => EntryTyParam(p
, n
),
117 fn parent_node(self) -> Option
<NodeId
> {
119 EntryItem(id
, _
) => id
,
120 EntryForeignItem(id
, _
) => id
,
121 EntryTraitItem(id
, _
) => id
,
122 EntryImplItem(id
, _
) => id
,
123 EntryVariant(id
, _
) => id
,
124 EntryExpr(id
, _
) => id
,
125 EntryStmt(id
, _
) => id
,
126 EntryTy(id
, _
) => id
,
127 EntryLocal(id
, _
) => id
,
128 EntryPat(id
, _
) => id
,
129 EntryBlock(id
, _
) => id
,
130 EntryStructCtor(id
, _
) => id
,
131 EntryLifetime(id
, _
) => id
,
132 EntryTyParam(id
, _
) => id
,
136 RootInlinedParent(_
) => return None
,
140 fn to_node(self) -> Option
<Node
<'ast
>> {
142 EntryItem(_
, n
) => NodeItem(n
),
143 EntryForeignItem(_
, n
) => NodeForeignItem(n
),
144 EntryTraitItem(_
, n
) => NodeTraitItem(n
),
145 EntryImplItem(_
, n
) => NodeImplItem(n
),
146 EntryVariant(_
, n
) => NodeVariant(n
),
147 EntryExpr(_
, n
) => NodeExpr(n
),
148 EntryStmt(_
, n
) => NodeStmt(n
),
149 EntryTy(_
, n
) => NodeTy(n
),
150 EntryLocal(_
, n
) => NodeLocal(n
),
151 EntryPat(_
, n
) => NodePat(n
),
152 EntryBlock(_
, n
) => NodeBlock(n
),
153 EntryStructCtor(_
, n
) => NodeStructCtor(n
),
154 EntryLifetime(_
, n
) => NodeLifetime(n
),
155 EntryTyParam(_
, n
) => NodeTyParam(n
),
161 /// Stores a crate and any number of inlined items from other crates.
164 pub dep_graph
: DepGraph
,
165 inlined_items
: TypedArena
<InlinedItem
>
169 pub fn new(krate
: Crate
, dep_graph
: &DepGraph
) -> Forest
{
172 dep_graph
: dep_graph
.clone(),
173 inlined_items
: TypedArena
::new()
177 pub fn krate
<'ast
>(&'ast
self) -> &'ast Crate
{
178 self.dep_graph
.read(DepNode
::Krate
);
183 /// Represents a mapping from Node IDs to AST elements and their parent
186 pub struct Map
<'ast
> {
187 /// The backing storage for all the AST nodes.
188 pub forest
: &'ast Forest
,
190 /// Same as the dep_graph in forest, just available with one fewer
191 /// deref. This is a gratuitious micro-optimization.
192 pub dep_graph
: DepGraph
,
194 /// NodeIds are sequential integers from 0, so we can be
195 /// super-compact by storing them in a vector. Not everything with
196 /// a NodeId is in the map, but empirically the occupancy is about
197 /// 75-80%, so there's not too much overhead (certainly less than
198 /// a hashmap, since they (at the time of writing) have a maximum
199 /// of 75% occupancy).
201 /// Also, indexing is pretty quick when you've got a vector and
202 /// plain old integers.
203 map
: RefCell
<Vec
<MapEntry
<'ast
>>>,
205 definitions
: RefCell
<Definitions
>,
207 /// All NodeIds that are numerically greater or equal to this value come
208 /// from inlined items.
209 local_node_id_watermark
: NodeId
,
211 /// All def-indices that are numerically greater or equal to this value come
212 /// from inlined items.
213 local_def_id_watermark
: usize,
216 impl<'ast
> Map
<'ast
> {
217 pub fn is_inlined_def_id(&self, id
: DefId
) -> bool
{
218 id
.is_local() && id
.index
.as_usize() >= self.local_def_id_watermark
221 pub fn is_inlined_node_id(&self, id
: NodeId
) -> bool
{
222 id
>= self.local_node_id_watermark
225 /// Registers a read in the dependency graph of the AST node with
226 /// the given `id`. This needs to be called each time a public
227 /// function returns the HIR for a node -- in other words, when it
228 /// "reveals" the content of a node to the caller (who might not
229 /// otherwise have had access to those contents, and hence needs a
230 /// read recorded). If the function just returns a DefId or
231 /// NodeId, no actual content was returned, so no read is needed.
232 pub fn read(&self, id
: NodeId
) {
233 self.dep_graph
.read(self.dep_node(id
));
236 fn dep_node(&self, id0
: NodeId
) -> DepNode
<DefId
> {
237 let map
= self.map
.borrow();
239 if !self.is_inlined_node_id(id
) {
241 match map
[id
.as_usize()] {
242 EntryItem(_
, item
) => {
243 let def_id
= self.local_def_id(item
.id
);
246 // You would expect that `item.id == id`, but this
247 // is not always the case. In particular, for a
248 // ViewPath item like `use self::{mem, foo}`, we
249 // map the ids for `mem` and `foo` to the
250 // enclosing view path item. This seems mega super
251 // ultra wrong, but then who am I to judge?
253 assert
!(!self.is_inlined_def_id(def_id
));
254 return DepNode
::Hir(def_id
);
257 EntryForeignItem(p
, _
) |
258 EntryTraitItem(p
, _
) |
259 EntryImplItem(p
, _
) |
267 EntryStructCtor(p
, _
) |
268 EntryLifetime(p
, _
) |
269 EntryTyParam(p
, _
) =>
273 return DepNode
::Krate
,
275 RootInlinedParent(_
) =>
276 bug
!("node {} has inlined ancestor but is not inlined", id0
),
279 // Some nodes, notably struct fields, are not
280 // present in the map for whatever reason, but
281 // they *do* have def-ids. So if we encounter an
282 // empty hole, check for that case.
283 return self.opt_local_def_id(id
)
284 .map(|def_id
| DepNode
::Hir(def_id
))
286 bug
!("Walking parents from `{}` \
287 led to `NotPresent` at `{}`",
293 // reading from an inlined def-id is really a read out of
294 // the metadata from which we loaded the item.
296 match map
[id
.as_usize()] {
298 EntryForeignItem(p
, _
) |
299 EntryTraitItem(p
, _
) |
300 EntryImplItem(p
, _
) |
308 EntryStructCtor(p
, _
) |
309 EntryLifetime(p
, _
) |
310 EntryTyParam(p
, _
) =>
313 RootInlinedParent(parent
) => match *parent
{
314 InlinedItem
::Item(def_id
, _
) |
315 InlinedItem
::TraitItem(def_id
, _
) |
316 InlinedItem
::ImplItem(def_id
, _
) =>
317 return DepNode
::MetaData(def_id
)
321 bug
!("node {} has crate ancestor but is inlined", id0
),
324 bug
!("node {} is inlined but not present in map", id0
),
330 pub fn num_local_def_ids(&self) -> usize {
331 self.definitions
.borrow().len()
334 pub fn def_key(&self, def_id
: DefId
) -> DefKey
{
335 assert
!(def_id
.is_local());
336 self.definitions
.borrow().def_key(def_id
.index
)
339 pub fn def_path_from_id(&self, id
: NodeId
) -> Option
<DefPath
> {
340 self.opt_local_def_id(id
).map(|def_id
| {
341 self.def_path(def_id
)
345 pub fn def_path(&self, def_id
: DefId
) -> DefPath
{
346 assert
!(def_id
.is_local());
347 self.definitions
.borrow().def_path(def_id
.index
)
350 pub fn def_index_for_def_key(&self, def_key
: DefKey
) -> Option
<DefIndex
> {
351 self.definitions
.borrow().def_index_for_def_key(def_key
)
354 pub fn local_def_id(&self, node
: NodeId
) -> DefId
{
355 self.opt_local_def_id(node
).unwrap_or_else(|| {
356 bug
!("local_def_id: no entry for `{}`, which has a map of `{:?}`",
357 node
, self.find_entry(node
))
361 pub fn opt_local_def_id(&self, node
: NodeId
) -> Option
<DefId
> {
362 self.definitions
.borrow().opt_local_def_id(node
)
365 pub fn as_local_node_id(&self, def_id
: DefId
) -> Option
<NodeId
> {
366 self.definitions
.borrow().as_local_node_id(def_id
)
369 fn entry_count(&self) -> usize {
370 self.map
.borrow().len()
373 fn find_entry(&self, id
: NodeId
) -> Option
<MapEntry
<'ast
>> {
374 self.map
.borrow().get(id
.as_usize()).cloned()
377 pub fn krate(&self) -> &'ast Crate
{
381 /// Get the attributes on the krate. This is preferable to
382 /// invoking `krate.attrs` because it registers a tighter
383 /// dep-graph access.
384 pub fn krate_attrs(&self) -> &'ast
[ast
::Attribute
] {
385 let crate_root_def_id
= DefId
::local(CRATE_DEF_INDEX
);
386 self.dep_graph
.read(DepNode
::Hir(crate_root_def_id
));
387 &self.forest
.krate
.attrs
390 /// Retrieve the Node corresponding to `id`, panicking if it cannot
392 pub fn get(&self, id
: NodeId
) -> Node
<'ast
> {
393 match self.find(id
) {
394 Some(node
) => node
, // read recorded by `find`
395 None
=> bug
!("couldn't find node id {} in the AST map", id
)
399 pub fn get_if_local(&self, id
: DefId
) -> Option
<Node
<'ast
>> {
400 self.as_local_node_id(id
).map(|id
| self.get(id
)) // read recorded by `get`
403 /// Retrieve the Node corresponding to `id`, returning None if
405 pub fn find(&self, id
: NodeId
) -> Option
<Node
<'ast
>> {
406 let result
= self.find_entry(id
).and_then(|x
| x
.to_node());
407 if result
.is_some() {
413 /// Similar to get_parent, returns the parent node id or id if there is no
415 /// This function returns the immediate parent in the AST, whereas get_parent
416 /// returns the enclosing item. Note that this might not be the actual parent
417 /// node in the AST - some kinds of nodes are not in the map and these will
418 /// never appear as the parent_node. So you can always walk the parent_nodes
419 /// from a node to the root of the ast (unless you get the same id back here
420 /// that can happen if the id is not in the map itself or is just weird).
421 pub fn get_parent_node(&self, id
: NodeId
) -> NodeId
{
422 self.find_entry(id
).and_then(|x
| x
.parent_node()).unwrap_or(id
)
425 /// Check if the node is an argument. An argument is a local variable whose
426 /// immediate parent is an item or a closure.
427 pub fn is_argument(&self, id
: NodeId
) -> bool
{
428 match self.find(id
) {
429 Some(NodeLocal(_
)) => (),
432 match self.find(self.get_parent_node(id
)) {
434 Some(NodeTraitItem(_
)) |
435 Some(NodeImplItem(_
)) => true,
436 Some(NodeExpr(e
)) => {
438 ExprClosure(..) => true,
446 /// If there is some error when walking the parents (e.g., a node does not
447 /// have a parent in the map or a node can't be found), then we return the
448 /// last good node id we found. Note that reaching the crate root (id == 0),
449 /// is not an error, since items in the crate module have the crate root as
451 fn walk_parent_nodes
<F
>(&self, start_id
: NodeId
, found
: F
) -> Result
<NodeId
, NodeId
>
452 where F
: Fn(&Node
<'ast
>) -> bool
454 let mut id
= start_id
;
456 let parent_node
= self.get_parent_node(id
);
457 if parent_node
== CRATE_NODE_ID
{
458 return Ok(CRATE_NODE_ID
);
460 if parent_node
== id
{
464 let node
= self.find_entry(parent_node
);
468 let node
= node
.unwrap().to_node();
472 return Ok(parent_node
);
476 return Err(parent_node
);
483 /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
484 /// parent item is in this map. The "parent item" is the closest parent node
485 /// in the AST which is recorded by the map and is an item, either an item
486 /// in a module, trait, or impl.
487 pub fn get_parent(&self, id
: NodeId
) -> NodeId
{
488 match self.walk_parent_nodes(id
, |node
| match *node
{
492 NodeImplItem(_
) => true,
500 /// Returns the NodeId of `id`'s nearest module parent, or `id` itself if no
501 /// module parent is in this map.
502 pub fn get_module_parent(&self, id
: NodeId
) -> NodeId
{
503 match self.walk_parent_nodes(id
, |node
| match *node
{
504 NodeItem(&Item { node: Item_::ItemMod(_), .. }
) => true,
512 /// Returns the nearest enclosing scope. A scope is an item or block.
513 /// FIXME it is not clear to me that all items qualify as scopes - statics
514 /// and associated types probably shouldn't, for example. Behaviour in this
515 /// regard should be expected to be highly unstable.
516 pub fn get_enclosing_scope(&self, id
: NodeId
) -> Option
<NodeId
> {
517 match self.walk_parent_nodes(id
, |node
| match *node
{
522 NodeBlock(_
) => true,
530 pub fn get_parent_did(&self, id
: NodeId
) -> DefId
{
531 let parent
= self.get_parent(id
);
532 match self.find_entry(parent
) {
533 Some(RootInlinedParent(&II
::TraitItem(did
, _
))) |
534 Some(RootInlinedParent(&II
::ImplItem(did
, _
))) => did
,
535 _
=> self.local_def_id(parent
)
539 pub fn get_foreign_abi(&self, id
: NodeId
) -> Abi
{
540 let parent
= self.get_parent(id
);
541 let abi
= match self.find_entry(parent
) {
542 Some(EntryItem(_
, i
)) => {
544 ItemForeignMod(ref nm
) => Some(nm
.abi
),
548 /// Wrong but OK, because the only inlined foreign items are intrinsics.
549 Some(RootInlinedParent(_
)) => Some(Abi
::RustIntrinsic
),
554 self.read(id
); // reveals some of the content of a node
557 None
=> bug
!("expected foreign mod or inlined parent, found {}",
558 self.node_to_string(parent
))
562 pub fn expect_item(&self, id
: NodeId
) -> &'ast Item
{
563 match self.find(id
) { // read recorded by `find`
564 Some(NodeItem(item
)) => item
,
565 _
=> bug
!("expected item, found {}", self.node_to_string(id
))
569 pub fn expect_impl_item(&self, id
: NodeId
) -> &'ast ImplItem
{
570 match self.find(id
) {
571 Some(NodeImplItem(item
)) => item
,
572 _
=> bug
!("expected impl item, found {}", self.node_to_string(id
))
576 pub fn expect_trait_item(&self, id
: NodeId
) -> &'ast TraitItem
{
577 match self.find(id
) {
578 Some(NodeTraitItem(item
)) => item
,
579 _
=> bug
!("expected trait item, found {}", self.node_to_string(id
))
583 pub fn expect_variant_data(&self, id
: NodeId
) -> &'ast VariantData
{
584 match self.find(id
) {
585 Some(NodeItem(i
)) => {
587 ItemStruct(ref struct_def
, _
) |
588 ItemUnion(ref struct_def
, _
) => struct_def
,
590 bug
!("struct ID bound to non-struct {}",
591 self.node_to_string(id
));
595 Some(NodeStructCtor(data
)) => data
,
596 Some(NodeVariant(variant
)) => &variant
.node
.data
,
598 bug
!("expected struct or variant, found {}",
599 self.node_to_string(id
));
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
)),
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
))
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
))
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
)),
632 /// Returns the name associated with the given NodeId's AST.
633 pub fn name(&self, id
: NodeId
) -> Name
{
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
))
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
));
670 /// Returns an iterator that yields the node id's with paths that
671 /// match `parts`. (Requires `parts` is non-empty.)
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
{
681 item_name
: parts
.last().unwrap(),
682 in_which
: &parts
[..parts
.len() - 1],
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
,
707 pub fn span(&self, id
: NodeId
) -> Span
{
708 self.read(id
); // reveals span from node
710 .unwrap_or_else(|| bug
!("AstMap.span: could not find span for id {:?}", id
))
713 pub fn span_if_local(&self, id
: DefId
) -> Option
<Span
> {
714 self.as_local_node_id(id
).map(|id
| self.span(id
))
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
)
725 pub fn node_to_string(&self, id
: NodeId
) -> String
{
726 node_id_to_string(self, id
, true)
729 pub fn node_to_user_string(&self, id
: NodeId
) -> String
{
730 node_id_to_string(self, id
, false)
734 pub struct NodesMatchingSuffix
<'a
, 'ast
:'a
> {
736 item_name
: &'a String
,
737 in_which
: &'a
[String
],
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`.
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
),
755 if &part
[..] != mod_name
.as_str() {
758 cursor
= self.map
.get_parent(mod_id
);
762 // Finds the first mod in parent chain for `id`, along with
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
)> {
772 Some(NodeItem(item
)) if item_is_mod(&item
) =>
773 return Some((id
, item
.name
)),
776 let parent
= map
.get_parent(id
);
777 if parent
== id { return None }
781 fn item_is_mod(item
: &Item
) -> bool
{
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
)
798 impl<'a
, 'ast
> Iterator
for NodesMatchingSuffix
<'a
, 'ast
> {
801 fn next(&mut self) -> Option
<NodeId
> {
804 if idx
.as_usize() >= self.map
.entry_count() {
807 self.idx
= NodeId
::from_u32(self.idx
.as_u32() + 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(),
816 if self.matches_names(self.map
.get_parent(idx
), name
) {
824 fn name(&self) -> Name
;
827 impl<T
:Named
> Named
for Spanned
<T
> { fn name(&self) -> Name { self.node.name() }
}
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 }
}
835 pub fn map_crate
<'ast
>(forest
: &'ast
mut Forest
,
836 definitions
: Definitions
)
838 let mut collector
= NodeCollector
::root(&forest
.krate
);
839 intravisit
::walk_crate(&mut collector
, &forest
.krate
);
840 let map
= collector
.map
;
842 if log_enabled
!(::log
::DEBUG
) {
843 // This only makes sense for ordered stores; note the
844 // enumerate to count the number of entries.
845 let (entries_less_1
, _
) = map
.iter().filter(|&x
| {
850 }).enumerate().last().expect("AST map was empty after folding?");
852 let entries
= entries_less_1
+ 1;
853 let vector_length
= map
.len();
854 debug
!("The AST map has {} entries with a maximum of {}: occupancy {:.1}%",
855 entries
, vector_length
, (entries
as f64 / vector_length
as f64) * 100.);
858 let local_node_id_watermark
= NodeId
::new(map
.len());
859 let local_def_id_watermark
= definitions
.len();
863 dep_graph
: forest
.dep_graph
.clone(),
864 map
: RefCell
::new(map
),
865 definitions
: RefCell
::new(definitions
),
866 local_node_id_watermark
: local_node_id_watermark
,
867 local_def_id_watermark
: local_def_id_watermark
,
871 /// Used for items loaded from external crate that are being inlined into this
873 pub fn map_decoded_item
<'ast
>(map
: &Map
<'ast
>,
874 parent_def_path
: DefPath
,
875 parent_def_id
: DefId
,
877 ii_parent_id
: NodeId
)
878 -> &'ast InlinedItem
{
879 let _ignore
= map
.forest
.dep_graph
.in_ignore();
881 let ii
= map
.forest
.inlined_items
.alloc(ii
);
883 let defs
= &mut *map
.definitions
.borrow_mut();
884 let mut def_collector
= DefCollector
::extend(ii_parent_id
,
885 parent_def_path
.clone(),
888 def_collector
.walk_item(ii
, map
.krate());
890 let mut collector
= NodeCollector
::extend(map
.krate(),
895 mem
::replace(&mut *map
.map
.borrow_mut(), vec
![]));
896 ii
.visit(&mut collector
);
897 *map
.map
.borrow_mut() = collector
.map
;
902 pub trait NodePrinter
{
903 fn print_node(&mut self, node
: &Node
) -> io
::Result
<()>;
906 impl<'a
> NodePrinter
for pprust
::State
<'a
> {
907 fn print_node(&mut self, node
: &Node
) -> io
::Result
<()> {
909 NodeItem(a
) => self.print_item(&a
),
910 NodeForeignItem(a
) => self.print_foreign_item(&a
),
911 NodeTraitItem(a
) => self.print_trait_item(a
),
912 NodeImplItem(a
) => self.print_impl_item(a
),
913 NodeVariant(a
) => self.print_variant(&a
),
914 NodeExpr(a
) => self.print_expr(&a
),
915 NodeStmt(a
) => self.print_stmt(&a
),
916 NodeTy(a
) => self.print_type(&a
),
917 NodePat(a
) => self.print_pat(&a
),
918 NodeBlock(a
) => self.print_block(&a
),
919 NodeLifetime(a
) => self.print_lifetime(&a
),
920 NodeTyParam(_
) => bug
!("cannot print TyParam"),
921 // these cases do not carry enough information in the
922 // ast_map to reconstruct their full structure for pretty
924 NodeLocal(_
) => bug
!("cannot print isolated Local"),
925 NodeStructCtor(_
) => bug
!("cannot print isolated StructCtor"),
930 fn node_id_to_string(map
: &Map
, id
: NodeId
, include_id
: bool
) -> String
{
931 let id_str
= format
!(" (id={})", id
);
932 let id_str
= if include_id { &id_str[..] }
else { "" }
;
935 // This functionality is used for debugging, try to use TyCtxt to get
936 // the user-friendly path, otherwise fall back to stringifying DefPath.
937 ::ty
::tls
::with_opt(|tcx
| {
938 if let Some(tcx
) = tcx
{
939 tcx
.node_path_str(id
)
940 } else if let Some(path
) = map
.def_path_from_id(id
) {
941 path
.data
.into_iter().map(|elem
| {
942 elem
.data
.to_string()
943 }).collect
::<Vec
<_
>>().join("::")
945 String
::from("<missing path>")
951 Some(NodeItem(item
)) => {
952 let item_str
= match item
.node
{
953 ItemExternCrate(..) => "extern crate",
954 ItemUse(..) => "use",
955 ItemStatic(..) => "static",
956 ItemConst(..) => "const",
958 ItemMod(..) => "mod",
959 ItemForeignMod(..) => "foreign mod",
961 ItemEnum(..) => "enum",
962 ItemStruct(..) => "struct",
963 ItemUnion(..) => "union",
964 ItemTrait(..) => "trait",
965 ItemImpl(..) => "impl",
966 ItemDefaultImpl(..) => "default impl",
968 format
!("{} {}{}", item_str
, path_str(), id_str
)
970 Some(NodeForeignItem(_
)) => {
971 format
!("foreign item {}{}", path_str(), id_str
)
973 Some(NodeImplItem(ii
)) => {
975 ImplItemKind
::Const(..) => {
976 format
!("assoc const {} in {}{}", ii
.name
, path_str(), id_str
)
978 ImplItemKind
::Method(..) => {
979 format
!("method {} in {}{}", ii
.name
, path_str(), id_str
)
981 ImplItemKind
::Type(_
) => {
982 format
!("assoc type {} in {}{}", ii
.name
, path_str(), id_str
)
986 Some(NodeTraitItem(ti
)) => {
987 let kind
= match ti
.node
{
988 ConstTraitItem(..) => "assoc constant",
989 MethodTraitItem(..) => "trait method",
990 TypeTraitItem(..) => "assoc type",
993 format
!("{} {} in {}{}", kind
, ti
.name
, path_str(), id_str
)
995 Some(NodeVariant(ref variant
)) => {
996 format
!("variant {} in {}{}",
1000 Some(NodeExpr(ref expr
)) => {
1001 format
!("expr {}{}", pprust
::expr_to_string(&expr
), id_str
)
1003 Some(NodeStmt(ref stmt
)) => {
1004 format
!("stmt {}{}", pprust
::stmt_to_string(&stmt
), id_str
)
1006 Some(NodeTy(ref ty
)) => {
1007 format
!("type {}{}", pprust
::ty_to_string(&ty
), id_str
)
1009 Some(NodeLocal(ref pat
)) => {
1010 format
!("local {}{}", pprust
::pat_to_string(&pat
), id_str
)
1012 Some(NodePat(ref pat
)) => {
1013 format
!("pat {}{}", pprust
::pat_to_string(&pat
), id_str
)
1015 Some(NodeBlock(ref block
)) => {
1016 format
!("block {}{}", pprust
::block_to_string(&block
), id_str
)
1018 Some(NodeStructCtor(_
)) => {
1019 format
!("struct_ctor {}{}", path_str(), id_str
)
1021 Some(NodeLifetime(ref l
)) => {
1022 format
!("lifetime {}{}",
1023 pprust
::lifetime_to_string(&l
), id_str
)
1025 Some(NodeTyParam(ref ty_param
)) => {
1026 format
!("typaram {:?}{}", ty_param
, id_str
)
1029 format
!("unknown node{}", id_str
)