1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use rustc::hir::def::Def;
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::hir::Node;
use rustc::hir::{ForeignMod, Mod};
use rustc::ty::TyCtxt;
use syntax::ast::Ident;
use syntax_pos::symbol::Symbol;
fn push_hir_mod_children(tcx: TyCtxt, m: &Mod, children: &mut Vec<(Symbol, Def)>) {
use rustc::hir::ItemKind::*;
for &iid in &m.item_ids {
let node = tcx.hir().get_by_hir_id(iid.id);
let item = expect!([node] Node::Item(i) => i);
match item.node {
ForeignMod(ref fm) => {
push_hir_foreign_mod_children(tcx, fm, children);
}
ExternCrate(..) => {
let item_did = tcx.hir().local_def_id_from_hir_id(item.hir_id);
let krate = tcx
.extern_mod_stmt_cnum(item_did)
.expect("no cnum available for `extern crate`");
let krate_did = DefId {
krate,
index: CRATE_DEF_INDEX,
};
let krate_def = Def::Mod(krate_did);
children.push((item.ident.name, krate_def));
}
_ => {
if let Some(def) = tcx.hir().describe_def_by_hir_id(item.hir_id) {
children.push((item.ident.name, def));
}
}
}
}
}
fn push_hir_foreign_mod_children(tcx: TyCtxt, fm: &ForeignMod, children: &mut Vec<(Symbol, Def)>) {
for fi in &fm.items {
if let Some(def) = tcx.hir().describe_def_by_hir_id(fi.hir_id) {
children.push((fi.ident.name, def));
}
}
}
pub fn module_children(tcx: TyCtxt, did: DefId) -> Vec<(Symbol, Def)> {
use rustc::hir::ItemKind::*;
if did.krate == LOCAL_CRATE {
if did.index == CRATE_DEF_INDEX {
let m = &tcx.hir().krate().module;
let mut children = Vec::with_capacity(m.item_ids.len());
push_hir_mod_children(tcx, m, &mut children);
return children;
}
let node = tcx
.hir()
.get_if_local(did)
.expect("definition not present in HIR map");
let item = expect!([node] Node::Item(i) => i);
match item.node {
ExternCrate(..) => {
let krate = tcx
.extern_mod_stmt_cnum(did)
.expect("no cnum available for `extern crate`");
let krate_did = DefId {
krate,
index: CRATE_DEF_INDEX,
};
module_children(tcx, krate_did)
}
Use(ref path, _kind) => {
let target_did = path.def.def_id();
module_children(tcx, target_did)
}
Mod(ref m) => {
let mut children = Vec::with_capacity(m.item_ids.len());
push_hir_mod_children(tcx, m, &mut children);
children
}
ForeignMod(ref fm) => {
let mut children = Vec::with_capacity(fm.items.len());
push_hir_foreign_mod_children(tcx, fm, &mut children);
children
}
ref it => panic!("item {:?} does not have resolvable children", it),
}
} else {
let children = tcx.item_children(did);
children.iter().map(|c| (c.ident.name, c.def)).collect()
}
}
pub fn resolve_absolute(tcx: TyCtxt, path: &[Ident]) -> Def {
let krate_did = DefId {
krate: LOCAL_CRATE,
index: CRATE_DEF_INDEX,
};
let mut cur_def = Def::Mod(krate_did);
'a: for ident in path {
for (sym, def) in module_children(tcx, cur_def.def_id()) {
if sym == ident.name {
cur_def = def;
continue 'a;
}
}
panic!("could not find {:?} in {:?}", ident, cur_def);
}
cur_def
}