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