]> git.lizzy.rs Git - rust.git/blob - src/librustc/hir/map/mod.rs
Rename `Stmt.node` to `Stmt.kind`
[rust.git] / src / librustc / hir / map / mod.rs
1 use self::collector::NodeCollector;
2 pub use self::def_collector::DefCollector;
3 pub use self::definitions::{
4     Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData, DefPathHash
5 };
6
7 use crate::dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex};
8 use crate::hir::*;
9 use crate::hir::DefKind;
10 use crate::hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId};
11 use crate::hir::itemlikevisit::ItemLikeVisitor;
12 use crate::hir::print::Nested;
13 use crate::middle::cstore::CrateStoreDyn;
14 use crate::ty::query::Providers;
15 use crate::util::nodemap::FxHashMap;
16 use crate::util::common::time;
17
18 use rustc_target::spec::abi::Abi;
19 use rustc_data_structures::svh::Svh;
20 use rustc_data_structures::indexed_vec::IndexVec;
21 use syntax::ast::{self, Name, NodeId};
22 use syntax::source_map::Spanned;
23 use syntax::ext::base::MacroKind;
24 use syntax_pos::{Span, DUMMY_SP};
25
26 use std::result::Result::Err;
27
28 pub mod blocks;
29 mod collector;
30 mod def_collector;
31 pub mod definitions;
32 mod hir_id_validator;
33
34 /// Represents an entry and its parent `HirId`.
35 #[derive(Copy, Clone, Debug)]
36 pub struct Entry<'hir> {
37     parent: HirId,
38     dep_node: DepNodeIndex,
39     node: Node<'hir>,
40 }
41
42 impl<'hir> Entry<'hir> {
43     fn parent_node(self) -> Option<HirId> {
44         match self.node {
45             Node::Crate | Node::MacroDef(_) => None,
46             _ => Some(self.parent),
47         }
48     }
49
50     fn fn_decl(&self) -> Option<&'hir FnDecl> {
51         match self.node {
52             Node::Item(ref item) => {
53                 match item.node {
54                     ItemKind::Fn(ref fn_decl, _, _, _) => Some(fn_decl),
55                     _ => None,
56                 }
57             }
58
59             Node::TraitItem(ref item) => {
60                 match item.kind {
61                     TraitItemKind::Method(ref method_sig, _) => Some(&method_sig.decl),
62                     _ => None
63                 }
64             }
65
66             Node::ImplItem(ref item) => {
67                 match item.kind {
68                     ImplItemKind::Method(ref method_sig, _) => Some(&method_sig.decl),
69                     _ => None,
70                 }
71             }
72
73             Node::Expr(ref expr) => {
74                 match expr.kind {
75                     ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl),
76                     _ => None,
77                 }
78             }
79
80             _ => None,
81         }
82     }
83
84     fn associated_body(self) -> Option<BodyId> {
85         match self.node {
86             Node::Item(item) => {
87                 match item.node {
88                     ItemKind::Const(_, body) |
89                     ItemKind::Static(.., body) |
90                     ItemKind::Fn(_, _, _, body) => Some(body),
91                     _ => None,
92                 }
93             }
94
95             Node::TraitItem(item) => {
96                 match item.kind {
97                     TraitItemKind::Const(_, Some(body)) |
98                     TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body),
99                     _ => None
100                 }
101             }
102
103             Node::ImplItem(item) => {
104                 match item.kind {
105                     ImplItemKind::Const(_, body) |
106                     ImplItemKind::Method(_, body) => Some(body),
107                     _ => None,
108                 }
109             }
110
111             Node::AnonConst(constant) => Some(constant.body),
112
113             Node::Expr(expr) => {
114                 match expr.kind {
115                     ExprKind::Closure(.., body, _, _) => Some(body),
116                     _ => None,
117                 }
118             }
119
120             _ => None
121         }
122     }
123
124     fn is_body_owner(self, hir_id: HirId) -> bool {
125         match self.associated_body() {
126             Some(b) => b.hir_id == hir_id,
127             None => false,
128         }
129     }
130 }
131
132 /// Stores a crate and any number of inlined items from other crates.
133 pub struct Forest {
134     krate: Crate,
135     pub dep_graph: DepGraph,
136 }
137
138 impl Forest {
139     pub fn new(krate: Crate, dep_graph: &DepGraph) -> Forest {
140         Forest {
141             krate,
142             dep_graph: dep_graph.clone(),
143         }
144     }
145
146     pub fn krate(&self) -> &Crate {
147         self.dep_graph.read(DepNode::new_no_params(DepKind::Krate));
148         &self.krate
149     }
150
151     /// This is used internally in the dependency tracking system.
152     /// Use the `krate` method to ensure your dependency on the
153     /// crate is tracked.
154     pub fn untracked_krate(&self) -> &Crate {
155         &self.krate
156     }
157 }
158
159 /// This type is effectively a `HashMap<HirId, Entry<'hir>>`,
160 /// but it is implemented as 2 layers of arrays.
161 /// - first we have `A = Vec<Option<B>>` mapping a `DefIndex`'s index to an inner value
162 /// - which is `B = IndexVec<ItemLocalId, Option<Entry<'hir>>` which gives you the `Entry`.
163 pub(super) type HirEntryMap<'hir> = Vec<Option<IndexVec<ItemLocalId, Option<Entry<'hir>>>>>;
164
165 /// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s.
166 #[derive(Clone)]
167 pub struct Map<'hir> {
168     /// The backing storage for all the AST nodes.
169     pub forest: &'hir Forest,
170
171     /// Same as the dep_graph in forest, just available with one fewer
172     /// deref. This is a gratuitous micro-optimization.
173     pub dep_graph: DepGraph,
174
175     /// The SVH of the local crate.
176     pub crate_hash: Svh,
177
178     map: HirEntryMap<'hir>,
179
180     definitions: &'hir Definitions,
181
182     /// The reverse mapping of `node_to_hir_id`.
183     hir_to_node_id: FxHashMap<HirId, NodeId>,
184 }
185
186 impl<'hir> Map<'hir> {
187     #[inline]
188     fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> {
189         let local_map = self.map.get(id.owner.index())?;
190         local_map.as_ref()?.get(id.local_id)?.as_ref()
191     }
192
193     /// Registers a read in the dependency graph of the AST node with
194     /// the given `id`. This needs to be called each time a public
195     /// function returns the HIR for a node -- in other words, when it
196     /// "reveals" the content of a node to the caller (who might not
197     /// otherwise have had access to those contents, and hence needs a
198     /// read recorded). If the function just returns a DefId or
199     /// HirId, no actual content was returned, so no read is needed.
200     pub fn read(&self, hir_id: HirId) {
201         if let Some(entry) = self.lookup(hir_id) {
202             self.dep_graph.read_index(entry.dep_node);
203         } else {
204             bug!("called `HirMap::read()` with invalid `HirId`: {:?}", hir_id)
205         }
206     }
207
208     #[inline]
209     pub fn definitions(&self) -> &'hir Definitions {
210         self.definitions
211     }
212
213     pub fn def_key(&self, def_id: DefId) -> DefKey {
214         assert!(def_id.is_local());
215         self.definitions.def_key(def_id.index)
216     }
217
218     pub fn def_path_from_hir_id(&self, id: HirId) -> Option<DefPath> {
219         self.opt_local_def_id(id).map(|def_id| {
220             self.def_path(def_id)
221         })
222     }
223
224     pub fn def_path(&self, def_id: DefId) -> DefPath {
225         assert!(def_id.is_local());
226         self.definitions.def_path(def_id.index)
227     }
228
229     #[inline]
230     pub fn local_def_id_from_node_id(&self, node: NodeId) -> DefId {
231         self.opt_local_def_id_from_node_id(node).unwrap_or_else(|| {
232             let hir_id = self.node_to_hir_id(node);
233             bug!("local_def_id_from_node_id: no entry for `{}`, which has a map of `{:?}`",
234                  node, self.find_entry(hir_id))
235         })
236     }
237
238     #[inline]
239     pub fn local_def_id(&self, hir_id: HirId) -> DefId {
240         self.opt_local_def_id(hir_id).unwrap_or_else(|| {
241             bug!("local_def_id: no entry for `{:?}`, which has a map of `{:?}`",
242                  hir_id, self.find_entry(hir_id))
243         })
244     }
245
246     #[inline]
247     pub fn opt_local_def_id(&self, hir_id: HirId) -> Option<DefId> {
248         let node_id = self.hir_to_node_id(hir_id);
249         self.definitions.opt_local_def_id(node_id)
250     }
251
252     #[inline]
253     pub fn opt_local_def_id_from_node_id(&self, node: NodeId) -> Option<DefId> {
254         self.definitions.opt_local_def_id(node)
255     }
256
257     #[inline]
258     pub fn as_local_node_id(&self, def_id: DefId) -> Option<NodeId> {
259         self.definitions.as_local_node_id(def_id)
260     }
261
262     #[inline]
263     pub fn as_local_hir_id(&self, def_id: DefId) -> Option<HirId> {
264         self.definitions.as_local_hir_id(def_id)
265     }
266
267     #[inline]
268     pub fn hir_to_node_id(&self, hir_id: HirId) -> NodeId {
269         self.hir_to_node_id[&hir_id]
270     }
271
272     #[inline]
273     pub fn node_to_hir_id(&self, node_id: NodeId) -> HirId {
274         self.definitions.node_to_hir_id(node_id)
275     }
276
277     #[inline]
278     pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> HirId {
279         self.definitions.def_index_to_hir_id(def_index)
280     }
281
282     #[inline]
283     pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId {
284         self.definitions.def_index_to_hir_id(def_id.to_def_id().index)
285     }
286
287     pub fn def_kind(&self, hir_id: HirId) -> Option<DefKind> {
288         let node = if let Some(node) = self.find(hir_id) {
289             node
290         } else {
291             return None
292         };
293
294         Some(match node {
295             Node::Item(item) => {
296                 match item.node {
297                     ItemKind::Static(..) => DefKind::Static,
298                     ItemKind::Const(..) => DefKind::Const,
299                     ItemKind::Fn(..) => DefKind::Fn,
300                     ItemKind::Mod(..) => DefKind::Mod,
301                     ItemKind::OpaqueTy(..) => DefKind::OpaqueTy,
302                     ItemKind::TyAlias(..) => DefKind::TyAlias,
303                     ItemKind::Enum(..) => DefKind::Enum,
304                     ItemKind::Struct(..) => DefKind::Struct,
305                     ItemKind::Union(..) => DefKind::Union,
306                     ItemKind::Trait(..) => DefKind::Trait,
307                     ItemKind::TraitAlias(..) => DefKind::TraitAlias,
308                     ItemKind::ExternCrate(_) |
309                     ItemKind::Use(..) |
310                     ItemKind::ForeignMod(..) |
311                     ItemKind::GlobalAsm(..) |
312                     ItemKind::Impl(..) => return None,
313                 }
314             }
315             Node::ForeignItem(item) => {
316                 match item.node {
317                     ForeignItemKind::Fn(..) => DefKind::Fn,
318                     ForeignItemKind::Static(..) => DefKind::Static,
319                     ForeignItemKind::Type => DefKind::ForeignTy,
320                 }
321             }
322             Node::TraitItem(item) => {
323                 match item.kind {
324                     TraitItemKind::Const(..) => DefKind::AssocConst,
325                     TraitItemKind::Method(..) => DefKind::Method,
326                     TraitItemKind::Type(..) => DefKind::AssocTy,
327                 }
328             }
329             Node::ImplItem(item) => {
330                 match item.kind {
331                     ImplItemKind::Const(..) => DefKind::AssocConst,
332                     ImplItemKind::Method(..) => DefKind::Method,
333                     ImplItemKind::TyAlias(..) => DefKind::AssocTy,
334                     ImplItemKind::OpaqueTy(..) => DefKind::AssocOpaqueTy,
335                 }
336             }
337             Node::Variant(_) => DefKind::Variant,
338             Node::Ctor(variant_data) => {
339                 // FIXME(eddyb) is this even possible, if we have a `Node::Ctor`?
340                 if variant_data.ctor_hir_id().is_none() {
341                     return None;
342                 }
343                 let ctor_of = match self.find(self.get_parent_node(hir_id)) {
344                     Some(Node::Item(..)) => def::CtorOf::Struct,
345                     Some(Node::Variant(..)) => def::CtorOf::Variant,
346                     _ => unreachable!(),
347                 };
348                 DefKind::Ctor(ctor_of, def::CtorKind::from_hir(variant_data))
349             }
350             Node::AnonConst(_) |
351             Node::Field(_) |
352             Node::Expr(_) |
353             Node::Stmt(_) |
354             Node::PathSegment(_) |
355             Node::Ty(_) |
356             Node::TraitRef(_) |
357             Node::Pat(_) |
358             Node::Binding(_) |
359             Node::Local(_) |
360             Node::Param(_) |
361             Node::Arm(_) |
362             Node::Lifetime(_) |
363             Node::Visibility(_) |
364             Node::Block(_) |
365             Node::Crate => return None,
366             Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
367             Node::GenericParam(param) => {
368                 match param.kind {
369                     GenericParamKind::Lifetime { .. } => return None,
370                     GenericParamKind::Type { .. } => DefKind::TyParam,
371                     GenericParamKind::Const { .. } => DefKind::ConstParam,
372                 }
373             }
374         })
375     }
376
377     fn find_entry(&self, id: HirId) -> Option<Entry<'hir>> {
378         self.lookup(id).cloned()
379     }
380
381     pub fn krate(&self) -> &'hir Crate {
382         self.forest.krate()
383     }
384
385     pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem {
386         self.read(id.hir_id);
387
388         // N.B., intentionally bypass `self.forest.krate()` so that we
389         // do not trigger a read of the whole krate here
390         self.forest.krate.trait_item(id)
391     }
392
393     pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem {
394         self.read(id.hir_id);
395
396         // N.B., intentionally bypass `self.forest.krate()` so that we
397         // do not trigger a read of the whole krate here
398         self.forest.krate.impl_item(id)
399     }
400
401     pub fn body(&self, id: BodyId) -> &'hir Body {
402         self.read(id.hir_id);
403
404         // N.B., intentionally bypass `self.forest.krate()` so that we
405         // do not trigger a read of the whole krate here
406         self.forest.krate.body(id)
407     }
408
409     pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl> {
410         if let Some(entry) = self.find_entry(hir_id) {
411             entry.fn_decl()
412         } else {
413             bug!("no entry for hir_id `{}`", hir_id)
414         }
415     }
416
417     /// Returns the `HirId` that corresponds to the definition of
418     /// which this is the body of, i.e., a `fn`, `const` or `static`
419     /// item (possibly associated), a closure, or a `hir::AnonConst`.
420     pub fn body_owner(&self, BodyId { hir_id }: BodyId) -> HirId {
421         let parent = self.get_parent_node(hir_id);
422         assert!(self.lookup(parent).map_or(false, |e| e.is_body_owner(hir_id)));
423         parent
424     }
425
426     pub fn body_owner_def_id(&self, id: BodyId) -> DefId {
427         self.local_def_id(self.body_owner(id))
428     }
429
430     /// Given a `HirId`, returns the `BodyId` associated with it,
431     /// if the node is a body owner, otherwise returns `None`.
432     pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option<BodyId> {
433         if let Some(entry) = self.find_entry(hir_id) {
434             if self.dep_graph.is_fully_enabled() {
435                 let hir_id_owner = hir_id.owner;
436                 let def_path_hash = self.definitions.def_path_hash(hir_id_owner);
437                 self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
438             }
439
440             entry.associated_body()
441         } else {
442             bug!("no entry for id `{}`", hir_id)
443         }
444     }
445
446     /// Given a body owner's id, returns the `BodyId` associated with it.
447     pub fn body_owned_by(&self, id: HirId) -> BodyId {
448         self.maybe_body_owned_by(id).unwrap_or_else(|| {
449             span_bug!(self.span(id), "body_owned_by: {} has no associated body",
450                       self.node_to_string(id));
451         })
452     }
453
454     pub fn body_owner_kind(&self, id: HirId) -> BodyOwnerKind {
455         match self.get(id) {
456             Node::Item(&Item { node: ItemKind::Const(..), .. }) |
457             Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) |
458             Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. }) |
459             Node::AnonConst(_) => {
460                 BodyOwnerKind::Const
461             }
462             Node::Ctor(..) |
463             Node::Item(&Item { node: ItemKind::Fn(..), .. }) |
464             Node::TraitItem(&TraitItem { kind: TraitItemKind::Method(..), .. }) |
465             Node::ImplItem(&ImplItem { kind: ImplItemKind::Method(..), .. }) => {
466                 BodyOwnerKind::Fn
467             }
468             Node::Item(&Item { node: ItemKind::Static(_, m, _), .. }) => {
469                 BodyOwnerKind::Static(m)
470             }
471             Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => {
472                 BodyOwnerKind::Closure
473             }
474             node => bug!("{:#?} is not a body node", node),
475         }
476     }
477
478     pub fn ty_param_owner(&self, id: HirId) -> HirId {
479         match self.get(id) {
480             Node::Item(&Item { node: ItemKind::Trait(..), .. }) |
481             Node::Item(&Item { node: ItemKind::TraitAlias(..), .. }) => id,
482             Node::GenericParam(_) => self.get_parent_node(id),
483             _ => bug!("ty_param_owner: {} not a type parameter", self.node_to_string(id))
484         }
485     }
486
487     pub fn ty_param_name(&self, id: HirId) -> Name {
488         match self.get(id) {
489             Node::Item(&Item { node: ItemKind::Trait(..), .. }) |
490             Node::Item(&Item { node: ItemKind::TraitAlias(..), .. }) => kw::SelfUpper,
491             Node::GenericParam(param) => param.name.ident().name,
492             _ => bug!("ty_param_name: {} not a type parameter", self.node_to_string(id)),
493         }
494     }
495
496     pub fn trait_impls(&self, trait_did: DefId) -> &'hir [HirId] {
497         self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls));
498
499         // N.B., intentionally bypass `self.forest.krate()` so that we
500         // do not trigger a read of the whole krate here
501         self.forest.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..])
502     }
503
504     /// Gets the attributes on the crate. This is preferable to
505     /// invoking `krate.attrs` because it registers a tighter
506     /// dep-graph access.
507     pub fn krate_attrs(&self) -> &'hir [ast::Attribute] {
508         let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX);
509
510         self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir));
511         &self.forest.krate.attrs
512     }
513
514     pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) {
515         let hir_id = self.as_local_hir_id(module).unwrap();
516         self.read(hir_id);
517         match self.find_entry(hir_id).unwrap().node {
518             Node::Item(&Item {
519                 span,
520                 node: ItemKind::Mod(ref m),
521                 ..
522             }) => (m, span, hir_id),
523             Node::Crate => (&self.forest.krate.module, self.forest.krate.span, hir_id),
524             node => panic!("not a module: {:?}", node),
525         }
526     }
527
528     pub fn visit_item_likes_in_module<V>(&self, module: DefId, visitor: &mut V)
529         where V: ItemLikeVisitor<'hir>
530     {
531         let hir_id = self.as_local_hir_id(module).unwrap();
532
533         // Read the module so we'll be re-executed if new items
534         // appear immediately under in the module. If some new item appears
535         // in some nested item in the module, we'll be re-executed due to reads
536         // in the expect_* calls the loops below
537         self.read(hir_id);
538
539         let module = &self.forest.krate.modules[&hir_id];
540
541         for id in &module.items {
542             visitor.visit_item(self.expect_item(*id));
543         }
544
545         for id in &module.trait_items {
546             visitor.visit_trait_item(self.expect_trait_item(id.hir_id));
547         }
548
549         for id in &module.impl_items {
550             visitor.visit_impl_item(self.expect_impl_item(id.hir_id));
551         }
552     }
553
554     /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
555     pub fn get(&self, id: HirId) -> Node<'hir> {
556         // read recorded by `find`
557         self.find(id).unwrap_or_else(||
558             bug!("couldn't find hir id {} in the HIR map", id))
559     }
560
561     pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> {
562         self.as_local_hir_id(id).map(|id| self.get(id)) // read recorded by `get`
563     }
564
565     pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics> {
566         self.get_if_local(id).and_then(|node| {
567             match node {
568                 Node::ImplItem(ref impl_item) => Some(&impl_item.generics),
569                 Node::TraitItem(ref trait_item) => Some(&trait_item.generics),
570                 Node::Item(ref item) => {
571                     match item.node {
572                         ItemKind::Fn(_, _, ref generics, _) |
573                         ItemKind::TyAlias(_, ref generics) |
574                         ItemKind::Enum(_, ref generics) |
575                         ItemKind::Struct(_, ref generics) |
576                         ItemKind::Union(_, ref generics) |
577                         ItemKind::Trait(_, _, ref generics, ..) |
578                         ItemKind::TraitAlias(ref generics, _) |
579                         ItemKind::Impl(_, _, _, ref generics, ..) => Some(generics),
580                         _ => None,
581                     }
582                 }
583                 _ => None,
584             }
585         })
586     }
587
588     /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
589     pub fn find(&self, hir_id: HirId) -> Option<Node<'hir>> {
590         let result = self.find_entry(hir_id).and_then(|entry| {
591             if let Node::Crate = entry.node {
592                 None
593             } else {
594                 Some(entry.node)
595             }
596         });
597         if result.is_some() {
598             self.read(hir_id);
599         }
600         result
601     }
602
603     /// Similar to `get_parent`; returns the parent HIR Id, or just `hir_id` if there
604     /// is no parent. Note that the parent may be `CRATE_HIR_ID`, which is not itself
605     /// present in the map, so passing the return value of `get_parent_node` to
606     /// `get` may in fact panic.
607     /// This function returns the immediate parent in the HIR, whereas `get_parent`
608     /// returns the enclosing item. Note that this might not be the actual parent
609     /// node in the HIR -- some kinds of nodes are not in the map and these will
610     /// never appear as the parent node. Thus, you can always walk the parent nodes
611     /// from a node to the root of the HIR (unless you get back the same ID here,
612     /// which can happen if the ID is not in the map itself or is just weird).
613     pub fn get_parent_node(&self, hir_id: HirId) -> HirId {
614         if self.dep_graph.is_fully_enabled() {
615             let hir_id_owner = hir_id.owner;
616             let def_path_hash = self.definitions.def_path_hash(hir_id_owner);
617             self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
618         }
619
620         self.find_entry(hir_id)
621             .and_then(|x| x.parent_node())
622             .unwrap_or(hir_id)
623     }
624
625     /// Checks if the node is an argument. An argument is a local variable whose
626     /// immediate parent is an item or a closure.
627     pub fn is_argument(&self, id: HirId) -> bool {
628         match self.find(id) {
629             Some(Node::Binding(_)) => (),
630             _ => return false,
631         }
632         match self.find(self.get_parent_node(id)) {
633             Some(Node::Item(_)) |
634             Some(Node::TraitItem(_)) |
635             Some(Node::ImplItem(_)) => true,
636             Some(Node::Expr(e)) => {
637                 match e.kind {
638                     ExprKind::Closure(..) => true,
639                     _ => false,
640                 }
641             }
642             _ => false,
643         }
644     }
645
646     /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
647     /// Used exclusively for diagnostics, to avoid suggestion function calls.
648     pub fn is_const_context(&self, hir_id: HirId) -> bool {
649         let parent_id = self.get_parent_item(hir_id);
650         match self.get(parent_id) {
651             Node::Item(&Item {
652                 node: ItemKind::Const(..),
653                 ..
654             })
655             | Node::TraitItem(&TraitItem {
656                 kind: TraitItemKind::Const(..),
657                 ..
658             })
659             | Node::ImplItem(&ImplItem {
660                 kind: ImplItemKind::Const(..),
661                 ..
662             })
663             | Node::AnonConst(_)
664             | Node::Item(&Item {
665                 node: ItemKind::Static(..),
666                 ..
667             }) => true,
668             Node::Item(&Item {
669                 node: ItemKind::Fn(_, header, ..),
670                 ..
671             }) => header.constness == Constness::Const,
672             _ => false,
673         }
674     }
675
676     /// Wether `hir_id` corresponds to a `mod` or a crate.
677     pub fn is_hir_id_module(&self, hir_id: HirId) -> bool {
678         match self.lookup(hir_id) {
679             Some(Entry { node: Node::Item(Item { node: ItemKind::Mod(_), .. }), .. }) |
680             Some(Entry { node: Node::Crate, .. }) => true,
681             _ => false,
682         }
683     }
684
685
686     /// If there is some error when walking the parents (e.g., a node does not
687     /// have a parent in the map or a node can't be found), then we return the
688     /// last good `HirId` we found. Note that reaching the crate root (`id == 0`),
689     /// is not an error, since items in the crate module have the crate root as
690     /// parent.
691     fn walk_parent_nodes<F, F2>(&self,
692                                 start_id: HirId,
693                                 found: F,
694                                 bail_early: F2)
695         -> Result<HirId, HirId>
696         where F: Fn(&Node<'hir>) -> bool, F2: Fn(&Node<'hir>) -> bool
697     {
698         let mut id = start_id;
699         loop {
700             let parent_id = self.get_parent_node(id);
701             if parent_id == CRATE_HIR_ID {
702                 return Ok(CRATE_HIR_ID);
703             }
704             if parent_id == id {
705                 return Err(id);
706             }
707
708             if let Some(entry) = self.find_entry(parent_id) {
709                 if let Node::Crate = entry.node {
710                     return Err(id);
711                 }
712                 if found(&entry.node) {
713                     return Ok(parent_id);
714                 } else if bail_early(&entry.node) {
715                     return Err(parent_id);
716                 }
717                 id = parent_id;
718             } else {
719                 return Err(id);
720             }
721         }
722     }
723
724     /// Retrieves the `HirId` for `id`'s enclosing method, unless there's a
725     /// `while` or `loop` before reaching it, as block tail returns are not
726     /// available in them.
727     ///
728     /// ```
729     /// fn foo(x: usize) -> bool {
730     ///     if x == 1 {
731     ///         true  // If `get_return_block` gets passed the `id` corresponding
732     ///     } else {  // to this, it will return `foo`'s `HirId`.
733     ///         false
734     ///     }
735     /// }
736     /// ```
737     ///
738     /// ```
739     /// fn foo(x: usize) -> bool {
740     ///     loop {
741     ///         true  // If `get_return_block` gets passed the `id` corresponding
742     ///     }         // to this, it will return `None`.
743     ///     false
744     /// }
745     /// ```
746     pub fn get_return_block(&self, id: HirId) -> Option<HirId> {
747         let match_fn = |node: &Node<'_>| {
748             match *node {
749                 Node::Item(_) |
750                 Node::ForeignItem(_) |
751                 Node::TraitItem(_) |
752                 Node::Expr(Expr { kind: ExprKind::Closure(..), ..}) |
753                 Node::ImplItem(_) => true,
754                 _ => false,
755             }
756         };
757         let match_non_returning_block = |node: &Node<'_>| {
758             match *node {
759                 Node::Expr(ref expr) => {
760                     match expr.kind {
761                         ExprKind::Loop(..) | ExprKind::Ret(..) => true,
762                         _ => false,
763                     }
764                 }
765                 _ => false,
766             }
767         };
768
769         self.walk_parent_nodes(id, match_fn, match_non_returning_block).ok()
770     }
771
772     /// Retrieves the `HirId` for `id`'s parent item, or `id` itself if no
773     /// parent item is in this map. The "parent item" is the closest parent node
774     /// in the HIR which is recorded by the map and is an item, either an item
775     /// in a module, trait, or impl.
776     pub fn get_parent_item(&self, hir_id: HirId) -> HirId {
777         match self.walk_parent_nodes(hir_id, |node| match *node {
778             Node::Item(_) |
779             Node::ForeignItem(_) |
780             Node::TraitItem(_) |
781             Node::ImplItem(_) => true,
782             _ => false,
783         }, |_| false) {
784             Ok(id) => id,
785             Err(id) => id,
786         }
787     }
788
789     /// Returns the `DefId` of `id`'s nearest module parent, or `id` itself if no
790     /// module parent is in this map.
791     pub fn get_module_parent(&self, id: HirId) -> DefId {
792         self.local_def_id(self.get_module_parent_node(id))
793     }
794
795     /// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no
796     /// module parent is in this map.
797     pub fn get_module_parent_node(&self, hir_id: HirId) -> HirId {
798         match self.walk_parent_nodes(hir_id, |node| match *node {
799             Node::Item(&Item { node: ItemKind::Mod(_), .. }) => true,
800             _ => false,
801         }, |_| false) {
802             Ok(id) => id,
803             Err(id) => id,
804         }
805     }
806
807     /// Returns the nearest enclosing scope. A scope is roughly an item or block.
808     pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option<HirId> {
809         self.walk_parent_nodes(hir_id, |node| match *node {
810             Node::Item(i) => {
811                 match i.node {
812                     ItemKind::Fn(..)
813                     | ItemKind::Mod(..)
814                     | ItemKind::Enum(..)
815                     | ItemKind::Struct(..)
816                     | ItemKind::Union(..)
817                     | ItemKind::Trait(..)
818                     | ItemKind::Impl(..) => true,
819                     _ => false,
820                 }
821             },
822             Node::ForeignItem(fi) => {
823                 match fi.node {
824                     ForeignItemKind::Fn(..) => true,
825                     _ => false,
826                 }
827             },
828             Node::TraitItem(ti) => {
829                 match ti.kind {
830                     TraitItemKind::Method(..) => true,
831                     _ => false,
832                 }
833             },
834             Node::ImplItem(ii) => {
835                 match ii.kind {
836                     ImplItemKind::Method(..) => true,
837                     _ => false,
838                 }
839             },
840             Node::Block(_) => true,
841             _ => false,
842         }, |_| false).ok()
843     }
844
845     /// Returns the defining scope for an opaque type definition.
846     pub fn get_defining_scope(&self, id: HirId) -> Option<HirId> {
847         let mut scope = id;
848         loop {
849             scope = self.get_enclosing_scope(scope)?;
850             if scope == CRATE_HIR_ID {
851                 return Some(CRATE_HIR_ID);
852             }
853             match self.get(scope) {
854                 Node::Item(i) => {
855                     match i.node {
856                         ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {}
857                         _ => break,
858                     }
859                 }
860                 Node::Block(_) => {}
861                 _ => break,
862             }
863         }
864         Some(scope)
865     }
866
867     pub fn get_parent_did(&self, id: HirId) -> DefId {
868         self.local_def_id(self.get_parent_item(id))
869     }
870
871     pub fn get_foreign_abi(&self, hir_id: HirId) -> Abi {
872         let parent = self.get_parent_item(hir_id);
873         if let Some(entry) = self.find_entry(parent) {
874             if let Entry {
875                 node: Node::Item(Item { node: ItemKind::ForeignMod(ref nm), .. }), .. } = entry
876             {
877                 self.read(hir_id); // reveals some of the content of a node
878                 return nm.abi;
879             }
880         }
881         bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent))
882     }
883
884     pub fn expect_item(&self, id: HirId) -> &'hir Item {
885         match self.find(id) { // read recorded by `find`
886             Some(Node::Item(item)) => item,
887             _ => bug!("expected item, found {}", self.node_to_string(id))
888         }
889     }
890
891     pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem {
892         match self.find(id) {
893             Some(Node::ImplItem(item)) => item,
894             _ => bug!("expected impl item, found {}", self.node_to_string(id))
895         }
896     }
897
898     pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem {
899         match self.find(id) {
900             Some(Node::TraitItem(item)) => item,
901             _ => bug!("expected trait item, found {}", self.node_to_string(id))
902         }
903     }
904
905     pub fn expect_variant_data(&self, id: HirId) -> &'hir VariantData {
906         match self.find(id) {
907             Some(Node::Item(i)) => {
908                 match i.node {
909                     ItemKind::Struct(ref struct_def, _) |
910                     ItemKind::Union(ref struct_def, _) => struct_def,
911                     _ => bug!("struct ID bound to non-struct {}", self.node_to_string(id))
912                 }
913             }
914             Some(Node::Variant(variant)) => &variant.data,
915             Some(Node::Ctor(data)) => data,
916             _ => bug!("expected struct or variant, found {}", self.node_to_string(id))
917         }
918     }
919
920     pub fn expect_variant(&self, id: HirId) -> &'hir Variant {
921         match self.find(id) {
922             Some(Node::Variant(variant)) => variant,
923             _ => bug!("expected variant, found {}", self.node_to_string(id)),
924         }
925     }
926
927     pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem {
928         match self.find(id) {
929             Some(Node::ForeignItem(item)) => item,
930             _ => bug!("expected foreign item, found {}", self.node_to_string(id))
931         }
932     }
933
934     pub fn expect_expr(&self, id: HirId) -> &'hir Expr {
935         match self.find(id) { // read recorded by find
936             Some(Node::Expr(expr)) => expr,
937             _ => bug!("expected expr, found {}", self.node_to_string(id))
938         }
939     }
940
941     pub fn name(&self, id: HirId) -> Name {
942         match self.get(id) {
943             Node::Item(i) => i.ident.name,
944             Node::ForeignItem(fi) => fi.ident.name,
945             Node::ImplItem(ii) => ii.ident.name,
946             Node::TraitItem(ti) => ti.ident.name,
947             Node::Variant(v) => v.ident.name,
948             Node::Field(f) => f.ident.name,
949             Node::Lifetime(lt) => lt.name.ident().name,
950             Node::GenericParam(param) => param.name.ident().name,
951             Node::Binding(&Pat { kind: PatKind::Binding(_, _, l, _), .. }) => l.name,
952             Node::Ctor(..) => self.name(self.get_parent_item(id)),
953             _ => bug!("no name for {}", self.node_to_string(id))
954         }
955     }
956
957     /// Given a node ID, gets a list of attributes associated with the AST
958     /// corresponding to the node-ID.
959     pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
960         self.read(id); // reveals attributes on the node
961         let attrs = match self.find_entry(id).map(|entry| entry.node) {
962             Some(Node::Param(a)) => Some(&a.attrs[..]),
963             Some(Node::Local(l)) => Some(&l.attrs[..]),
964             Some(Node::Item(i)) => Some(&i.attrs[..]),
965             Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]),
966             Some(Node::TraitItem(ref ti)) => Some(&ti.attrs[..]),
967             Some(Node::ImplItem(ref ii)) => Some(&ii.attrs[..]),
968             Some(Node::Variant(ref v)) => Some(&v.attrs[..]),
969             Some(Node::Field(ref f)) => Some(&f.attrs[..]),
970             Some(Node::Expr(ref e)) => Some(&*e.attrs),
971             Some(Node::Stmt(ref s)) => Some(s.kind.attrs()),
972             Some(Node::Arm(ref a)) => Some(&*a.attrs),
973             Some(Node::GenericParam(param)) => Some(&param.attrs[..]),
974             // Unit/tuple structs/variants take the attributes straight from
975             // the struct/variant definition.
976             Some(Node::Ctor(..)) => return self.attrs(self.get_parent_item(id)),
977             Some(Node::Crate) => Some(&self.forest.krate.attrs[..]),
978             _ => None
979         };
980         attrs.unwrap_or(&[])
981     }
982
983     /// Returns an iterator that yields all the hir ids in the map.
984     fn all_ids<'a>(&'a self) -> impl Iterator<Item = HirId> + 'a {
985         // This code is a bit awkward because the map is implemented as 2 levels of arrays,
986         // see the comment on `HirEntryMap`.
987         // Iterate over all the indices and return a reference to
988         // local maps and their index given that they exist.
989         self.map.iter().enumerate().filter_map(|(i, local_map)| {
990             local_map.as_ref().map(|m| (i, m))
991         }).flat_map(move |(array_index, local_map)| {
992             // Iterate over each valid entry in the local map.
993             local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| {
994                 // Reconstruct the `HirId` based on the 3 indices we used to find it.
995                 HirId {
996                     owner: DefIndex::from(array_index),
997                     local_id: i,
998                 }
999             }))
1000         })
1001     }
1002
1003     /// Returns an iterator that yields the node id's with paths that
1004     /// match `parts`.  (Requires `parts` is non-empty.)
1005     ///
1006     /// For example, if given `parts` equal to `["bar", "quux"]`, then
1007     /// the iterator will produce node id's for items with paths
1008     /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
1009     /// any other such items it can find in the map.
1010     pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String])
1011                                  -> impl Iterator<Item = NodeId> + 'a {
1012         let nodes = NodesMatchingSuffix {
1013             map: self,
1014             item_name: parts.last().unwrap(),
1015             in_which: &parts[..parts.len() - 1],
1016         };
1017
1018         self.all_ids().filter(move |hir| nodes.matches_suffix(*hir)).map(move |hir| {
1019             self.hir_to_node_id(hir)
1020         })
1021     }
1022
1023     pub fn span(&self, hir_id: HirId) -> Span {
1024         self.read(hir_id); // reveals span from node
1025         match self.find_entry(hir_id).map(|entry| entry.node) {
1026             Some(Node::Param(param)) => param.span,
1027             Some(Node::Item(item)) => item.span,
1028             Some(Node::ForeignItem(foreign_item)) => foreign_item.span,
1029             Some(Node::TraitItem(trait_method)) => trait_method.span,
1030             Some(Node::ImplItem(impl_item)) => impl_item.span,
1031             Some(Node::Variant(variant)) => variant.span,
1032             Some(Node::Field(field)) => field.span,
1033             Some(Node::AnonConst(constant)) => self.body(constant.body).value.span,
1034             Some(Node::Expr(expr)) => expr.span,
1035             Some(Node::Stmt(stmt)) => stmt.span,
1036             Some(Node::PathSegment(seg)) => seg.ident.span,
1037             Some(Node::Ty(ty)) => ty.span,
1038             Some(Node::TraitRef(tr)) => tr.path.span,
1039             Some(Node::Binding(pat)) => pat.span,
1040             Some(Node::Pat(pat)) => pat.span,
1041             Some(Node::Arm(arm)) => arm.span,
1042             Some(Node::Block(block)) => block.span,
1043             Some(Node::Ctor(..)) => match self.find(
1044                 self.get_parent_node(hir_id))
1045             {
1046                 Some(Node::Item(item)) => item.span,
1047                 Some(Node::Variant(variant)) => variant.span,
1048                 _ => unreachable!(),
1049             }
1050             Some(Node::Lifetime(lifetime)) => lifetime.span,
1051             Some(Node::GenericParam(param)) => param.span,
1052             Some(Node::Visibility(&Spanned {
1053                 node: VisibilityKind::Restricted { ref path, .. }, ..
1054             })) => path.span,
1055             Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v),
1056             Some(Node::Local(local)) => local.span,
1057             Some(Node::MacroDef(macro_def)) => macro_def.span,
1058             Some(Node::Crate) => self.forest.krate.span,
1059             None => bug!("hir::map::Map::span: id not in map: {:?}", hir_id),
1060         }
1061     }
1062
1063     pub fn span_if_local(&self, id: DefId) -> Option<Span> {
1064         self.as_local_hir_id(id).map(|id| self.span(id))
1065     }
1066
1067     pub fn node_to_string(&self, id: HirId) -> String {
1068         hir_id_to_string(self, id, true)
1069     }
1070
1071     pub fn hir_to_user_string(&self, id: HirId) -> String {
1072         hir_id_to_string(self, id, false)
1073     }
1074
1075     pub fn hir_to_pretty_string(&self, id: HirId) -> String {
1076         print::to_string(self, |s| s.print_node(self.get(id)))
1077     }
1078 }
1079
1080 pub struct NodesMatchingSuffix<'a> {
1081     map: &'a Map<'a>,
1082     item_name: &'a String,
1083     in_which: &'a [String],
1084 }
1085
1086 impl<'a> NodesMatchingSuffix<'a> {
1087     /// Returns `true` only if some suffix of the module path for parent
1088     /// matches `self.in_which`.
1089     ///
1090     /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`;
1091     /// returns true if parent's path ends with the suffix
1092     /// `x_0::x_1::...::x_k`.
1093     fn suffix_matches(&self, parent: HirId) -> bool {
1094         let mut cursor = parent;
1095         for part in self.in_which.iter().rev() {
1096             let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) {
1097                 None => return false,
1098                 Some((node_id, name)) => (node_id, name),
1099             };
1100             if mod_name.as_str() != *part {
1101                 return false;
1102             }
1103             cursor = self.map.get_parent_item(mod_id);
1104         }
1105         return true;
1106
1107         // Finds the first mod in parent chain for `id`, along with
1108         // that mod's name.
1109         //
1110         // If `id` itself is a mod named `m` with parent `p`, then
1111         // returns `Some(id, m, p)`.  If `id` has no mod in its parent
1112         // chain, then returns `None`.
1113         fn find_first_mod_parent(map: &Map<'_>, mut id: HirId) -> Option<(HirId, Name)> {
1114             loop {
1115                 if let Node::Item(item) = map.find(id)? {
1116                     if item_is_mod(&item) {
1117                         return Some((id, item.ident.name))
1118                     }
1119                 }
1120                 let parent = map.get_parent_item(id);
1121                 if parent == id { return None }
1122                 id = parent;
1123             }
1124
1125             fn item_is_mod(item: &Item) -> bool {
1126                 match item.node {
1127                     ItemKind::Mod(_) => true,
1128                     _ => false,
1129                 }
1130             }
1131         }
1132     }
1133
1134     // We are looking at some node `n` with a given name and parent
1135     // id; do their names match what I am seeking?
1136     fn matches_names(&self, parent_of_n: HirId, name: Name) -> bool {
1137         name.as_str() == *self.item_name && self.suffix_matches(parent_of_n)
1138     }
1139
1140     fn matches_suffix(&self, hir: HirId) -> bool {
1141         let name = match self.map.find_entry(hir).map(|entry| entry.node) {
1142             Some(Node::Item(n)) => n.name(),
1143             Some(Node::ForeignItem(n)) => n.name(),
1144             Some(Node::TraitItem(n)) => n.name(),
1145             Some(Node::ImplItem(n)) => n.name(),
1146             Some(Node::Variant(n)) => n.name(),
1147             Some(Node::Field(n)) => n.name(),
1148             _ => return false,
1149         };
1150         self.matches_names(self.map.get_parent_item(hir), name)
1151     }
1152 }
1153
1154 trait Named {
1155     fn name(&self) -> Name;
1156 }
1157
1158 impl<T:Named> Named for Spanned<T> { fn name(&self) -> Name { self.node.name() } }
1159
1160 impl Named for Item { fn name(&self) -> Name { self.ident.name } }
1161 impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } }
1162 impl Named for Variant { fn name(&self) -> Name { self.ident.name } }
1163 impl Named for StructField { fn name(&self) -> Name { self.ident.name } }
1164 impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } }
1165 impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } }
1166
1167 pub fn map_crate<'hir>(sess: &crate::session::Session,
1168                        cstore: &CrateStoreDyn,
1169                        forest: &'hir Forest,
1170                        definitions: &'hir Definitions)
1171                        -> Map<'hir> {
1172     // Build the reverse mapping of `node_to_hir_id`.
1173     let hir_to_node_id = definitions.node_to_hir_id.iter_enumerated()
1174         .map(|(node_id, &hir_id)| (hir_id, node_id)).collect();
1175
1176     let (map, crate_hash) = {
1177         let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore);
1178
1179         let mut collector = NodeCollector::root(sess,
1180                                                 &forest.krate,
1181                                                 &forest.dep_graph,
1182                                                 &definitions,
1183                                                 &hir_to_node_id,
1184                                                 hcx);
1185         intravisit::walk_crate(&mut collector, &forest.krate);
1186
1187         let crate_disambiguator = sess.local_crate_disambiguator();
1188         let cmdline_args = sess.opts.dep_tracking_hash();
1189         collector.finalize_and_compute_crate_hash(
1190             crate_disambiguator,
1191             cstore,
1192             cmdline_args
1193         )
1194     };
1195
1196     let map = Map {
1197         forest,
1198         dep_graph: forest.dep_graph.clone(),
1199         crate_hash,
1200         map,
1201         hir_to_node_id,
1202         definitions,
1203     };
1204
1205     time(sess, "validate HIR map", || {
1206         hir_id_validator::check_crate(&map);
1207     });
1208
1209     map
1210 }
1211
1212 /// Identical to the `PpAnn` implementation for `hir::Crate`,
1213 /// except it avoids creating a dependency on the whole crate.
1214 impl<'hir> print::PpAnn for Map<'hir> {
1215     fn nested(&self, state: &mut print::State<'_>, nested: print::Nested) {
1216         match nested {
1217             Nested::Item(id) => state.print_item(self.expect_item(id.id)),
1218             Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
1219             Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
1220             Nested::Body(id) => state.print_expr(&self.body(id).value),
1221             Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat)
1222         }
1223     }
1224 }
1225
1226 impl<'a> print::State<'a> {
1227     pub fn print_node(&mut self, node: Node<'_>) {
1228         match node {
1229             Node::Param(a)        => self.print_param(&a),
1230             Node::Item(a)         => self.print_item(&a),
1231             Node::ForeignItem(a)  => self.print_foreign_item(&a),
1232             Node::TraitItem(a)    => self.print_trait_item(a),
1233             Node::ImplItem(a)     => self.print_impl_item(a),
1234             Node::Variant(a)      => self.print_variant(&a),
1235             Node::AnonConst(a)    => self.print_anon_const(&a),
1236             Node::Expr(a)         => self.print_expr(&a),
1237             Node::Stmt(a)         => self.print_stmt(&a),
1238             Node::PathSegment(a)  => self.print_path_segment(&a),
1239             Node::Ty(a)           => self.print_type(&a),
1240             Node::TraitRef(a)     => self.print_trait_ref(&a),
1241             Node::Binding(a)      |
1242             Node::Pat(a)          => self.print_pat(&a),
1243             Node::Arm(a)          => self.print_arm(&a),
1244             Node::Block(a)        => {
1245                 // Containing cbox, will be closed by print-block at `}`.
1246                 self.cbox(print::INDENT_UNIT);
1247                 // Head-ibox, will be closed by print-block after `{`.
1248                 self.ibox(0);
1249                 self.print_block(&a)
1250             }
1251             Node::Lifetime(a)     => self.print_lifetime(&a),
1252             Node::Visibility(a)   => self.print_visibility(&a),
1253             Node::GenericParam(_) => bug!("cannot print Node::GenericParam"),
1254             Node::Field(_)        => bug!("cannot print StructField"),
1255             // These cases do not carry enough information in the
1256             // `hir_map` to reconstruct their full structure for pretty
1257             // printing.
1258             Node::Ctor(..)        => bug!("cannot print isolated Ctor"),
1259             Node::Local(a)        => self.print_local_decl(&a),
1260             Node::MacroDef(_)     => bug!("cannot print MacroDef"),
1261             Node::Crate           => bug!("cannot print Crate"),
1262         }
1263     }
1264 }
1265
1266 fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
1267     let id_str = format!(" (hir_id={})", id);
1268     let id_str = if include_id { &id_str[..] } else { "" };
1269
1270     let path_str = || {
1271         // This functionality is used for debugging, try to use `TyCtxt` to get
1272         // the user-friendly path, otherwise fall back to stringifying `DefPath`.
1273         crate::ty::tls::with_opt(|tcx| {
1274             if let Some(tcx) = tcx {
1275                 let def_id = map.local_def_id(id);
1276                 tcx.def_path_str(def_id)
1277             } else if let Some(path) = map.def_path_from_hir_id(id) {
1278                 path.data.into_iter().map(|elem| {
1279                     elem.data.to_string()
1280                 }).collect::<Vec<_>>().join("::")
1281             } else {
1282                 String::from("<missing path>")
1283             }
1284         })
1285     };
1286
1287     match map.find(id) {
1288         Some(Node::Item(item)) => {
1289             let item_str = match item.node {
1290                 ItemKind::ExternCrate(..) => "extern crate",
1291                 ItemKind::Use(..) => "use",
1292                 ItemKind::Static(..) => "static",
1293                 ItemKind::Const(..) => "const",
1294                 ItemKind::Fn(..) => "fn",
1295                 ItemKind::Mod(..) => "mod",
1296                 ItemKind::ForeignMod(..) => "foreign mod",
1297                 ItemKind::GlobalAsm(..) => "global asm",
1298                 ItemKind::TyAlias(..) => "ty",
1299                 ItemKind::OpaqueTy(..) => "opaque type",
1300                 ItemKind::Enum(..) => "enum",
1301                 ItemKind::Struct(..) => "struct",
1302                 ItemKind::Union(..) => "union",
1303                 ItemKind::Trait(..) => "trait",
1304                 ItemKind::TraitAlias(..) => "trait alias",
1305                 ItemKind::Impl(..) => "impl",
1306             };
1307             format!("{} {}{}", item_str, path_str(), id_str)
1308         }
1309         Some(Node::ForeignItem(_)) => {
1310             format!("foreign item {}{}", path_str(), id_str)
1311         }
1312         Some(Node::ImplItem(ii)) => {
1313             match ii.kind {
1314                 ImplItemKind::Const(..) => {
1315                     format!("assoc const {} in {}{}", ii.ident, path_str(), id_str)
1316                 }
1317                 ImplItemKind::Method(..) => {
1318                     format!("method {} in {}{}", ii.ident, path_str(), id_str)
1319                 }
1320                 ImplItemKind::TyAlias(_) => {
1321                     format!("assoc type {} in {}{}", ii.ident, path_str(), id_str)
1322                 }
1323                 ImplItemKind::OpaqueTy(_) => {
1324                     format!("assoc opaque type {} in {}{}", ii.ident, path_str(), id_str)
1325                 }
1326             }
1327         }
1328         Some(Node::TraitItem(ti)) => {
1329             let kind = match ti.kind {
1330                 TraitItemKind::Const(..) => "assoc constant",
1331                 TraitItemKind::Method(..) => "trait method",
1332                 TraitItemKind::Type(..) => "assoc type",
1333             };
1334
1335             format!("{} {} in {}{}", kind, ti.ident, path_str(), id_str)
1336         }
1337         Some(Node::Variant(ref variant)) => {
1338             format!("variant {} in {}{}",
1339                     variant.ident,
1340                     path_str(), id_str)
1341         }
1342         Some(Node::Field(ref field)) => {
1343             format!("field {} in {}{}",
1344                     field.ident,
1345                     path_str(), id_str)
1346         }
1347         Some(Node::AnonConst(_)) => {
1348             format!("const {}{}", map.hir_to_pretty_string(id), id_str)
1349         }
1350         Some(Node::Expr(_)) => {
1351             format!("expr {}{}", map.hir_to_pretty_string(id), id_str)
1352         }
1353         Some(Node::Stmt(_)) => {
1354             format!("stmt {}{}", map.hir_to_pretty_string(id), id_str)
1355         }
1356         Some(Node::PathSegment(_)) => {
1357             format!("path segment {}{}", map.hir_to_pretty_string(id), id_str)
1358         }
1359         Some(Node::Ty(_)) => {
1360             format!("type {}{}", map.hir_to_pretty_string(id), id_str)
1361         }
1362         Some(Node::TraitRef(_)) => {
1363             format!("trait_ref {}{}", map.hir_to_pretty_string(id), id_str)
1364         }
1365         Some(Node::Binding(_)) => {
1366             format!("local {}{}", map.hir_to_pretty_string(id), id_str)
1367         }
1368         Some(Node::Pat(_)) => {
1369             format!("pat {}{}", map.hir_to_pretty_string(id), id_str)
1370         }
1371         Some(Node::Param(_)) => {
1372             format!("param {}{}", map.hir_to_pretty_string(id), id_str)
1373         }
1374         Some(Node::Arm(_)) => {
1375             format!("arm {}{}", map.hir_to_pretty_string(id), id_str)
1376         }
1377         Some(Node::Block(_)) => {
1378             format!("block {}{}", map.hir_to_pretty_string(id), id_str)
1379         }
1380         Some(Node::Local(_)) => {
1381             format!("local {}{}", map.hir_to_pretty_string(id), id_str)
1382         }
1383         Some(Node::Ctor(..)) => {
1384             format!("ctor {}{}", path_str(), id_str)
1385         }
1386         Some(Node::Lifetime(_)) => {
1387             format!("lifetime {}{}", map.hir_to_pretty_string(id), id_str)
1388         }
1389         Some(Node::GenericParam(ref param)) => {
1390             format!("generic_param {:?}{}", param, id_str)
1391         }
1392         Some(Node::Visibility(ref vis)) => {
1393             format!("visibility {:?}{}", vis, id_str)
1394         }
1395         Some(Node::MacroDef(_)) => {
1396             format!("macro {}{}",  path_str(), id_str)
1397         }
1398         Some(Node::Crate) => String::from("root_crate"),
1399         None => format!("unknown node{}", id_str),
1400     }
1401 }
1402
1403 pub fn provide(providers: &mut Providers<'_>) {
1404     providers.def_kind = |tcx, def_id| {
1405         if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
1406             tcx.hir().def_kind(hir_id)
1407         } else {
1408             bug!("calling local def_kind query provider for upstream DefId: {:?}",
1409                 def_id
1410             );
1411         }
1412     };
1413 }