]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
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 | //! Reduced graph building | |
12 | //! | |
13 | //! Here we build the "reduced graph": the graph of the module tree without | |
14 | //! any imports resolved. | |
15 | ||
d9579d0f | 16 | use DefModifiers; |
54a0048b | 17 | use resolve_imports::ImportDirectiveSubclass::{self, GlobImport}; |
1a4d82fc | 18 | use Module; |
7453a54e SL |
19 | use Namespace::{self, TypeNS, ValueNS}; |
20 | use {NameBinding, NameBindingKind}; | |
9cc50fc6 | 21 | use ParentLink::{ModuleParentLink, BlockParentLink}; |
1a4d82fc | 22 | use Resolver; |
9cc50fc6 | 23 | use {resolve_error, resolve_struct_error, ResolutionError}; |
1a4d82fc | 24 | |
54a0048b SL |
25 | use rustc::middle::cstore::{CrateStore, ChildItem, DlDef}; |
26 | use rustc::lint; | |
27 | use rustc::hir::def::*; | |
28 | use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; | |
29 | use rustc::ty::{self, VariantKind}; | |
1a4d82fc | 30 | |
54a0048b | 31 | use syntax::ast::Name; |
b039eaaf | 32 | use syntax::attr::AttrMetaMethods; |
54a0048b | 33 | use syntax::parse::token::{special_idents, SELF_KEYWORD_NAME, SUPER_KEYWORD_NAME}; |
1a4d82fc | 34 | use syntax::codemap::{Span, DUMMY_SP}; |
e9174d1e | 35 | |
54a0048b SL |
36 | use rustc::hir; |
37 | use rustc::hir::{Block, DeclItem}; | |
38 | use rustc::hir::{ForeignItem, ForeignItemFn, ForeignItemStatic}; | |
39 | use rustc::hir::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn}; | |
40 | use rustc::hir::{ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl}; | |
41 | use rustc::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse}; | |
42 | use rustc::hir::{PathListIdent, PathListMod, StmtDecl}; | |
43 | use rustc::hir::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}; | |
44 | use rustc::hir::intravisit::{self, Visitor}; | |
1a4d82fc | 45 | |
7453a54e SL |
46 | trait ToNameBinding<'a> { |
47 | fn to_name_binding(self) -> NameBinding<'a>; | |
48 | } | |
49 | ||
50 | impl<'a> ToNameBinding<'a> for (Module<'a>, Span) { | |
51 | fn to_name_binding(self) -> NameBinding<'a> { | |
52 | NameBinding::create_from_module(self.0, Some(self.1)) | |
53 | } | |
54 | } | |
55 | ||
56 | impl<'a> ToNameBinding<'a> for (Def, Span, DefModifiers) { | |
57 | fn to_name_binding(self) -> NameBinding<'a> { | |
58 | let kind = NameBindingKind::Def(self.0); | |
59 | NameBinding { modifiers: self.2, kind: kind, span: Some(self.1) } | |
60 | } | |
61 | } | |
62 | ||
54a0048b | 63 | impl<'b, 'tcx:'b> Resolver<'b, 'tcx> { |
1a4d82fc | 64 | /// Constructs the reduced graph for the entire crate. |
54a0048b | 65 | pub fn build_reduced_graph(&mut self, krate: &hir::Crate) { |
1a4d82fc | 66 | let mut visitor = BuildReducedGraphVisitor { |
9cc50fc6 | 67 | parent: self.graph_root, |
54a0048b | 68 | resolver: self, |
1a4d82fc | 69 | }; |
92a42be0 | 70 | intravisit::walk_crate(&mut visitor, krate); |
1a4d82fc JJ |
71 | } |
72 | ||
7453a54e SL |
73 | /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined. |
74 | fn try_define<T>(&self, parent: Module<'b>, name: Name, ns: Namespace, def: T) | |
75 | where T: ToNameBinding<'b> | |
76 | { | |
54a0048b | 77 | let _ = parent.try_define_child(name, ns, def.to_name_binding()); |
7453a54e SL |
78 | } |
79 | ||
80 | /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; | |
81 | /// otherwise, reports an error. | |
82 | fn define<T: ToNameBinding<'b>>(&self, parent: Module<'b>, name: Name, ns: Namespace, def: T) { | |
54a0048b SL |
83 | let binding = def.to_name_binding(); |
84 | if let Err(old_binding) = parent.try_define_child(name, ns, binding.clone()) { | |
85 | self.report_conflict(parent, name, ns, old_binding, &binding); | |
1a4d82fc JJ |
86 | } |
87 | } | |
88 | ||
89 | fn block_needs_anonymous_module(&mut self, block: &Block) -> bool { | |
7453a54e SL |
90 | fn is_item(statement: &hir::Stmt) -> bool { |
91 | if let StmtDecl(ref declaration, _) = statement.node { | |
92 | if let DeclItem(_) = declaration.node { | |
93 | return true; | |
1a4d82fc JJ |
94 | } |
95 | } | |
7453a54e | 96 | false |
1a4d82fc JJ |
97 | } |
98 | ||
7453a54e SL |
99 | // If any statements are items, we need to create an anonymous module |
100 | block.stmts.iter().any(is_item) | |
1a4d82fc JJ |
101 | } |
102 | ||
1a4d82fc | 103 | /// Constructs the reduced graph for one item. |
54a0048b SL |
104 | fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<'b>) { |
105 | let parent = *parent_ref; | |
b039eaaf | 106 | let name = item.name; |
1a4d82fc | 107 | let sp = item.span; |
e9174d1e | 108 | let is_public = item.vis == hir::Public; |
d9579d0f AL |
109 | let modifiers = if is_public { |
110 | DefModifiers::PUBLIC | |
111 | } else { | |
112 | DefModifiers::empty() | |
113 | } | DefModifiers::IMPORTABLE; | |
1a4d82fc JJ |
114 | |
115 | match item.node { | |
85aaf69f SL |
116 | ItemUse(ref view_path) => { |
117 | // Extract and intern the module part of the path. For | |
118 | // globs and lists, the path is found directly in the AST; | |
119 | // for simple paths we have to munge the path a little. | |
54a0048b SL |
120 | let is_global; |
121 | let module_path: Vec<Name> = match view_path.node { | |
85aaf69f | 122 | ViewPathSimple(_, ref full_path) => { |
54a0048b | 123 | is_global = full_path.global; |
85aaf69f | 124 | full_path.segments |
92a42be0 SL |
125 | .split_last() |
126 | .unwrap() | |
127 | .1 | |
128 | .iter() | |
129 | .map(|seg| seg.identifier.name) | |
130 | .collect() | |
85aaf69f SL |
131 | } |
132 | ||
133 | ViewPathGlob(ref module_ident_path) | | |
134 | ViewPathList(ref module_ident_path, _) => { | |
54a0048b | 135 | is_global = module_ident_path.global; |
85aaf69f | 136 | module_ident_path.segments |
92a42be0 SL |
137 | .iter() |
138 | .map(|seg| seg.identifier.name) | |
139 | .collect() | |
85aaf69f SL |
140 | } |
141 | }; | |
142 | ||
54a0048b SL |
143 | // Checking for special identifiers in path |
144 | // prevent `self` or `super` at beginning of global path | |
145 | if is_global && (module_path.first() == Some(&SELF_KEYWORD_NAME) || | |
146 | module_path.first() == Some(&SUPER_KEYWORD_NAME)) { | |
147 | self.session.add_lint( | |
148 | lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH, | |
149 | item.id, | |
150 | item.span, | |
151 | format!("expected identifier, found keyword `{}`", | |
152 | module_path.first().unwrap().as_str())); | |
153 | } | |
154 | ||
85aaf69f | 155 | // Build up the import directives. |
54a0048b | 156 | let is_prelude = item.attrs.iter().any(|attr| { |
c1a9b12d | 157 | attr.name() == special_idents::prelude_import.name.as_str() |
85aaf69f | 158 | }); |
85aaf69f SL |
159 | |
160 | match view_path.node { | |
161 | ViewPathSimple(binding, ref full_path) => { | |
92a42be0 | 162 | let source_name = full_path.segments.last().unwrap().identifier.name; |
c1a9b12d SL |
163 | if source_name.as_str() == "mod" || source_name.as_str() == "self" { |
164 | resolve_error(self, | |
165 | view_path.span, | |
166 | ResolutionError::SelfImportsOnlyAllowedWithin); | |
85aaf69f SL |
167 | } |
168 | ||
54a0048b SL |
169 | let subclass = ImportDirectiveSubclass::single(binding, source_name); |
170 | self.unresolved_imports += 1; | |
171 | parent.add_import_directive(module_path, | |
85aaf69f SL |
172 | subclass, |
173 | view_path.span, | |
174 | item.id, | |
175 | is_public, | |
54a0048b | 176 | is_prelude); |
85aaf69f SL |
177 | } |
178 | ViewPathList(_, ref source_items) => { | |
179 | // Make sure there's at most one `mod` import in the list. | |
92a42be0 SL |
180 | let mod_spans = source_items.iter() |
181 | .filter_map(|item| { | |
182 | match item.node { | |
183 | PathListMod { .. } => Some(item.span), | |
184 | _ => None, | |
185 | } | |
186 | }) | |
187 | .collect::<Vec<Span>>(); | |
85aaf69f | 188 | if mod_spans.len() > 1 { |
9cc50fc6 | 189 | let mut e = resolve_struct_error(self, |
92a42be0 SL |
190 | mod_spans[0], |
191 | ResolutionError::SelfImportCanOnlyAppearOnceInTheList); | |
85aaf69f | 192 | for other_span in mod_spans.iter().skip(1) { |
9cc50fc6 | 193 | e.span_note(*other_span, "another `self` import appears here"); |
85aaf69f | 194 | } |
9cc50fc6 | 195 | e.emit(); |
85aaf69f SL |
196 | } |
197 | ||
198 | for source_item in source_items { | |
e9174d1e SL |
199 | let (module_path, name, rename) = match source_item.node { |
200 | PathListIdent { name, rename, .. } => | |
b039eaaf | 201 | (module_path.clone(), name, rename.unwrap_or(name)), |
e9174d1e | 202 | PathListMod { rename, .. } => { |
85aaf69f SL |
203 | let name = match module_path.last() { |
204 | Some(name) => *name, | |
205 | None => { | |
c1a9b12d SL |
206 | resolve_error( |
207 | self, | |
208 | source_item.span, | |
209 | ResolutionError:: | |
210 | SelfImportOnlyInImportListWithNonEmptyPrefix | |
211 | ); | |
85aaf69f SL |
212 | continue; |
213 | } | |
214 | }; | |
c1a9b12d | 215 | let module_path = module_path.split_last().unwrap().1; |
b039eaaf | 216 | let rename = rename.unwrap_or(name); |
e9174d1e | 217 | (module_path.to_vec(), name, rename) |
85aaf69f SL |
218 | } |
219 | }; | |
54a0048b SL |
220 | let subclass = ImportDirectiveSubclass::single(rename, name); |
221 | self.unresolved_imports += 1; | |
222 | parent.add_import_directive(module_path, | |
223 | subclass, | |
92a42be0 SL |
224 | source_item.span, |
225 | source_item.node.id(), | |
226 | is_public, | |
54a0048b | 227 | is_prelude); |
85aaf69f SL |
228 | } |
229 | } | |
230 | ViewPathGlob(_) => { | |
54a0048b SL |
231 | self.unresolved_imports += 1; |
232 | parent.add_import_directive(module_path, | |
85aaf69f SL |
233 | GlobImport, |
234 | view_path.span, | |
235 | item.id, | |
236 | is_public, | |
54a0048b | 237 | is_prelude); |
85aaf69f SL |
238 | } |
239 | } | |
85aaf69f SL |
240 | } |
241 | ||
242 | ItemExternCrate(_) => { | |
92a42be0 SL |
243 | // n.b. we don't need to look at the path option here, because cstore already |
244 | // did | |
245 | if let Some(crate_id) = self.session.cstore.extern_mod_stmt_cnum(item.id) { | |
246 | let def_id = DefId { | |
247 | krate: crate_id, | |
248 | index: CRATE_DEF_INDEX, | |
249 | }; | |
9cc50fc6 | 250 | let parent_link = ModuleParentLink(parent, name); |
7453a54e | 251 | let def = Def::Mod(def_id); |
54a0048b SL |
252 | let module = self.new_extern_crate_module(parent_link, def, is_public, item.id); |
253 | self.define(parent, name, TypeNS, (module, sp)); | |
7453a54e | 254 | |
54a0048b | 255 | self.build_reduced_graph_for_external_crate(module); |
85aaf69f | 256 | } |
85aaf69f SL |
257 | } |
258 | ||
1a4d82fc | 259 | ItemMod(..) => { |
9cc50fc6 | 260 | let parent_link = ModuleParentLink(parent, name); |
7453a54e | 261 | let def = Def::Mod(self.ast_map.local_def_id(item.id)); |
9cc50fc6 | 262 | let module = self.new_module(parent_link, Some(def), false, is_public); |
7453a54e SL |
263 | self.define(parent, name, TypeNS, (module, sp)); |
264 | parent.module_children.borrow_mut().insert(item.id, module); | |
54a0048b | 265 | *parent_ref = module; |
1a4d82fc JJ |
266 | } |
267 | ||
54a0048b | 268 | ItemForeignMod(..) => {} |
1a4d82fc JJ |
269 | |
270 | // These items live in the value namespace. | |
271 | ItemStatic(_, m, _) => { | |
e9174d1e | 272 | let mutbl = m == hir::MutMutable; |
7453a54e SL |
273 | let def = Def::Static(self.ast_map.local_def_id(item.id), mutbl); |
274 | self.define(parent, name, ValueNS, (def, sp, modifiers)); | |
1a4d82fc JJ |
275 | } |
276 | ItemConst(_, _) => { | |
7453a54e SL |
277 | let def = Def::Const(self.ast_map.local_def_id(item.id)); |
278 | self.define(parent, name, ValueNS, (def, sp, modifiers)); | |
1a4d82fc | 279 | } |
62682a34 | 280 | ItemFn(_, _, _, _, _, _) => { |
7453a54e SL |
281 | let def = Def::Fn(self.ast_map.local_def_id(item.id)); |
282 | self.define(parent, name, ValueNS, (def, sp, modifiers)); | |
1a4d82fc JJ |
283 | } |
284 | ||
285 | // These items live in the type namespace. | |
286 | ItemTy(..) => { | |
7453a54e | 287 | let def = Def::TyAlias(self.ast_map.local_def_id(item.id)); |
54a0048b | 288 | self.define(parent, name, TypeNS, (def, sp, modifiers)); |
1a4d82fc JJ |
289 | } |
290 | ||
291 | ItemEnum(ref enum_definition, _) => { | |
9cc50fc6 | 292 | let parent_link = ModuleParentLink(parent, name); |
7453a54e | 293 | let def = Def::Enum(self.ast_map.local_def_id(item.id)); |
9cc50fc6 | 294 | let module = self.new_module(parent_link, Some(def), false, is_public); |
7453a54e | 295 | self.define(parent, name, TypeNS, (module, sp)); |
1a4d82fc | 296 | |
9cc50fc6 SL |
297 | let variant_modifiers = if is_public { |
298 | DefModifiers::empty() | |
299 | } else { | |
300 | DefModifiers::PRIVATE_VARIANT | |
301 | }; | |
85aaf69f | 302 | for variant in &(*enum_definition).variants { |
b039eaaf | 303 | let item_def_id = self.ast_map.local_def_id(item.id); |
9cc50fc6 | 304 | self.build_reduced_graph_for_variant(variant, item_def_id, |
7453a54e | 305 | module, variant_modifiers); |
1a4d82fc | 306 | } |
1a4d82fc JJ |
307 | } |
308 | ||
309 | // These items live in both the type and value namespaces. | |
310 | ItemStruct(ref struct_def, _) => { | |
1a4d82fc | 311 | // Define a name in the type namespace. |
7453a54e SL |
312 | let def = Def::Struct(self.ast_map.local_def_id(item.id)); |
313 | self.define(parent, name, TypeNS, (def, sp, modifiers)); | |
1a4d82fc JJ |
314 | |
315 | // If this is a newtype or unit-like struct, define a name | |
316 | // in the value namespace as well | |
7453a54e SL |
317 | if !struct_def.is_struct() { |
318 | let def = Def::Struct(self.ast_map.local_def_id(struct_def.id())); | |
319 | self.define(parent, name, ValueNS, (def, sp, modifiers)); | |
1a4d82fc JJ |
320 | } |
321 | ||
322 | // Record the def ID and fields of this struct. | |
54a0048b SL |
323 | let field_names = struct_def.fields() |
324 | .iter() | |
325 | .map(|f| f.name) | |
326 | .collect(); | |
b039eaaf | 327 | let item_def_id = self.ast_map.local_def_id(item.id); |
54a0048b | 328 | self.structs.insert(item_def_id, field_names); |
1a4d82fc JJ |
329 | } |
330 | ||
54a0048b | 331 | ItemDefaultImpl(_, _) | ItemImpl(..) => {} |
1a4d82fc JJ |
332 | |
333 | ItemTrait(_, _, _, ref items) => { | |
92a42be0 | 334 | let def_id = self.ast_map.local_def_id(item.id); |
1a4d82fc JJ |
335 | |
336 | // Add all the items within to a new module. | |
9cc50fc6 | 337 | let parent_link = ModuleParentLink(parent, name); |
7453a54e | 338 | let def = Def::Trait(def_id); |
9cc50fc6 | 339 | let module_parent = self.new_module(parent_link, Some(def), false, is_public); |
7453a54e | 340 | self.define(parent, name, TypeNS, (module_parent, sp)); |
1a4d82fc JJ |
341 | |
342 | // Add the names of all the items to the trait info. | |
7453a54e SL |
343 | for item in items { |
344 | let item_def_id = self.ast_map.local_def_id(item.id); | |
345 | let (def, ns) = match item.node { | |
346 | hir::ConstTraitItem(..) => (Def::AssociatedConst(item_def_id), ValueNS), | |
347 | hir::MethodTraitItem(..) => (Def::Method(item_def_id), ValueNS), | |
348 | hir::TypeTraitItem(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS), | |
349 | }; | |
1a4d82fc | 350 | |
7453a54e SL |
351 | let modifiers = DefModifiers::PUBLIC; // NB: not DefModifiers::IMPORTABLE |
352 | self.define(module_parent, item.name, ns, (def, item.span, modifiers)); | |
353 | ||
354 | self.trait_item_map.insert((item.name, def_id), item_def_id); | |
1a4d82fc | 355 | } |
1a4d82fc | 356 | } |
1a4d82fc JJ |
357 | } |
358 | } | |
359 | ||
360 | // Constructs the reduced graph for one variant. Variants exist in the | |
361 | // type and value namespaces. | |
362 | fn build_reduced_graph_for_variant(&mut self, | |
363 | variant: &Variant, | |
364 | item_id: DefId, | |
9cc50fc6 SL |
365 | parent: Module<'b>, |
366 | variant_modifiers: DefModifiers) { | |
b039eaaf | 367 | let name = variant.node.name; |
7453a54e | 368 | if variant.node.data.is_struct() { |
b039eaaf SL |
369 | // Not adding fields for variants as they are not accessed with a self receiver |
370 | let variant_def_id = self.ast_map.local_def_id(variant.node.data.id()); | |
371 | self.structs.insert(variant_def_id, Vec::new()); | |
7453a54e SL |
372 | } |
373 | ||
374 | // Variants are always treated as importable to allow them to be glob used. | |
375 | // All variants are defined in both type and value namespaces as future-proofing. | |
376 | let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE | variant_modifiers; | |
377 | let def = Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id())); | |
1a4d82fc | 378 | |
7453a54e SL |
379 | self.define(parent, name, ValueNS, (def, variant.span, modifiers)); |
380 | self.define(parent, name, TypeNS, (def, variant.span, modifiers)); | |
1a4d82fc JJ |
381 | } |
382 | ||
1a4d82fc | 383 | /// Constructs the reduced graph for one foreign item. |
c34b1796 AL |
384 | fn build_reduced_graph_for_foreign_item(&mut self, |
385 | foreign_item: &ForeignItem, | |
9cc50fc6 | 386 | parent: Module<'b>) { |
b039eaaf | 387 | let name = foreign_item.name; |
e9174d1e | 388 | let is_public = foreign_item.vis == hir::Public; |
d9579d0f AL |
389 | let modifiers = if is_public { |
390 | DefModifiers::PUBLIC | |
391 | } else { | |
392 | DefModifiers::empty() | |
393 | } | DefModifiers::IMPORTABLE; | |
1a4d82fc | 394 | |
c34b1796 AL |
395 | let def = match foreign_item.node { |
396 | ForeignItemFn(..) => { | |
7453a54e | 397 | Def::Fn(self.ast_map.local_def_id(foreign_item.id)) |
1a4d82fc JJ |
398 | } |
399 | ForeignItemStatic(_, m) => { | |
7453a54e | 400 | Def::Static(self.ast_map.local_def_id(foreign_item.id), m) |
1a4d82fc | 401 | } |
c34b1796 | 402 | }; |
7453a54e | 403 | self.define(parent, name, ValueNS, (def, foreign_item.span, modifiers)); |
1a4d82fc JJ |
404 | } |
405 | ||
54a0048b | 406 | fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &mut Module<'b>) { |
1a4d82fc JJ |
407 | if self.block_needs_anonymous_module(block) { |
408 | let block_id = block.id; | |
409 | ||
92a42be0 SL |
410 | debug!("(building reduced graph for block) creating a new anonymous module for block \ |
411 | {}", | |
1a4d82fc JJ |
412 | block_id); |
413 | ||
9cc50fc6 SL |
414 | let parent_link = BlockParentLink(parent, block_id); |
415 | let new_module = self.new_module(parent_link, None, false, false); | |
7453a54e | 416 | parent.module_children.borrow_mut().insert(block_id, new_module); |
54a0048b | 417 | *parent = new_module; |
1a4d82fc JJ |
418 | } |
419 | } | |
420 | ||
54a0048b SL |
421 | /// Builds the reduced graph for a single item in an external crate. |
422 | fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, xcdef: ChildItem) { | |
423 | let def = match xcdef.def { | |
424 | DlDef(def) => def, | |
425 | _ => return, | |
426 | }; | |
427 | ||
428 | if let Def::ForeignMod(def_id) = def { | |
429 | // Foreign modules have no names. Recur and populate eagerly. | |
430 | for child in self.session.cstore.item_children(def_id) { | |
431 | self.build_reduced_graph_for_external_crate_def(parent, child); | |
432 | } | |
433 | return; | |
434 | } | |
435 | ||
436 | let name = xcdef.name; | |
437 | let is_public = xcdef.vis == ty::Visibility::Public || parent.is_trait(); | |
7453a54e SL |
438 | |
439 | let mut modifiers = DefModifiers::empty(); | |
440 | if is_public { | |
441 | modifiers = modifiers | DefModifiers::PUBLIC; | |
442 | } | |
54a0048b | 443 | if parent.is_normal() { |
7453a54e SL |
444 | modifiers = modifiers | DefModifiers::IMPORTABLE; |
445 | } | |
446 | ||
1a4d82fc | 447 | match def { |
54a0048b | 448 | Def::Mod(_) | Def::ForeignMod(_) | Def::Enum(..) => { |
7453a54e | 449 | debug!("(building reduced graph for external crate) building module {} {}", |
54a0048b | 450 | name, |
7453a54e | 451 | is_public); |
54a0048b | 452 | let parent_link = ModuleParentLink(parent, name); |
7453a54e | 453 | let module = self.new_module(parent_link, Some(def), true, is_public); |
54a0048b | 454 | self.try_define(parent, name, TypeNS, (module, DUMMY_SP)); |
1a4d82fc | 455 | } |
7453a54e | 456 | Def::Variant(_, variant_id) => { |
54a0048b | 457 | debug!("(building reduced graph for external crate) building variant {}", name); |
7453a54e SL |
458 | // Variants are always treated as importable to allow them to be glob used. |
459 | // All variants are defined in both type and value namespaces as future-proofing. | |
92a42be0 | 460 | let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE; |
54a0048b SL |
461 | self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers)); |
462 | self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers)); | |
7453a54e | 463 | if self.session.cstore.variant_kind(variant_id) == Some(VariantKind::Struct) { |
92a42be0 SL |
464 | // Not adding fields for variants as they are not accessed with a self receiver |
465 | self.structs.insert(variant_id, Vec::new()); | |
92a42be0 SL |
466 | } |
467 | } | |
7453a54e SL |
468 | Def::Fn(..) | |
469 | Def::Static(..) | | |
470 | Def::Const(..) | | |
471 | Def::AssociatedConst(..) | | |
472 | Def::Method(..) => { | |
92a42be0 | 473 | debug!("(building reduced graph for external crate) building value (fn/static) {}", |
54a0048b SL |
474 | name); |
475 | self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers)); | |
1a4d82fc | 476 | } |
7453a54e | 477 | Def::Trait(def_id) => { |
54a0048b | 478 | debug!("(building reduced graph for external crate) building type {}", name); |
92a42be0 SL |
479 | |
480 | // If this is a trait, add all the trait item names to the trait | |
481 | // info. | |
1a4d82fc | 482 | |
92a42be0 SL |
483 | let trait_item_def_ids = self.session.cstore.trait_item_def_ids(def_id); |
484 | for trait_item_def in &trait_item_def_ids { | |
485 | let trait_item_name = | |
486 | self.session.cstore.item_name(trait_item_def.def_id()); | |
487 | ||
488 | debug!("(building reduced graph for external crate) ... adding trait item \ | |
489 | '{}'", | |
490 | trait_item_name); | |
491 | ||
492 | self.trait_item_map.insert((trait_item_name, def_id), trait_item_def.def_id()); | |
92a42be0 SL |
493 | } |
494 | ||
54a0048b | 495 | let parent_link = ModuleParentLink(parent, name); |
9cc50fc6 | 496 | let module = self.new_module(parent_link, Some(def), true, is_public); |
54a0048b | 497 | self.try_define(parent, name, TypeNS, (module, DUMMY_SP)); |
92a42be0 | 498 | } |
54a0048b SL |
499 | Def::TyAlias(..) | Def::AssociatedTy(..) => { |
500 | debug!("(building reduced graph for external crate) building type {}", name); | |
501 | self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers)); | |
92a42be0 | 502 | } |
7453a54e SL |
503 | Def::Struct(def_id) |
504 | if self.session.cstore.tuple_struct_definition_if_ctor(def_id).is_none() => { | |
54a0048b SL |
505 | debug!("(building reduced graph for external crate) building type and value for {}", |
506 | name); | |
507 | self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers)); | |
7453a54e SL |
508 | if let Some(ctor_def_id) = self.session.cstore.struct_ctor_def_id(def_id) { |
509 | let def = Def::Struct(ctor_def_id); | |
54a0048b | 510 | self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers)); |
92a42be0 SL |
511 | } |
512 | ||
513 | // Record the def ID and fields of this struct. | |
7453a54e | 514 | let fields = self.session.cstore.struct_field_names(def_id); |
92a42be0 SL |
515 | self.structs.insert(def_id, fields); |
516 | } | |
7453a54e SL |
517 | Def::Struct(..) => {} |
518 | Def::Local(..) | | |
519 | Def::PrimTy(..) | | |
520 | Def::TyParam(..) | | |
521 | Def::Upvar(..) | | |
522 | Def::Label(..) | | |
523 | Def::SelfTy(..) | | |
524 | Def::Err => { | |
54a0048b | 525 | bug!("didn't expect `{:?}`", def); |
92a42be0 | 526 | } |
1a4d82fc JJ |
527 | } |
528 | } | |
529 | ||
1a4d82fc JJ |
530 | /// Builds the reduced graph rooted at the 'use' directive for an external |
531 | /// crate. | |
9cc50fc6 | 532 | fn build_reduced_graph_for_external_crate(&mut self, root: Module<'b>) { |
92a42be0 SL |
533 | let root_cnum = root.def_id().unwrap().krate; |
534 | for child in self.session.cstore.crate_top_level_items(root_cnum) { | |
535 | self.build_reduced_graph_for_external_crate_def(root, child); | |
536 | } | |
1a4d82fc JJ |
537 | } |
538 | ||
54a0048b SL |
539 | /// Ensures that the reduced graph rooted at the given external module |
540 | /// is built, building it if it is not. | |
541 | pub fn populate_module_if_necessary(&mut self, module: Module<'b>) { | |
542 | if module.populated.get() { return } | |
543 | for child in self.session.cstore.item_children(module.def_id().unwrap()) { | |
544 | self.build_reduced_graph_for_external_crate_def(module, child); | |
1a4d82fc | 545 | } |
54a0048b | 546 | module.populated.set(true) |
1a4d82fc JJ |
547 | } |
548 | } | |
549 | ||
92a42be0 | 550 | struct BuildReducedGraphVisitor<'a, 'b: 'a, 'tcx: 'b> { |
54a0048b | 551 | resolver: &'a mut Resolver<'b, 'tcx>, |
9cc50fc6 | 552 | parent: Module<'b>, |
1a4d82fc JJ |
553 | } |
554 | ||
555 | impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { | |
92a42be0 | 556 | fn visit_nested_item(&mut self, item: hir::ItemId) { |
54a0048b | 557 | self.visit_item(self.resolver.ast_map.expect_item(item.id)) |
92a42be0 SL |
558 | } |
559 | ||
1a4d82fc | 560 | fn visit_item(&mut self, item: &Item) { |
54a0048b SL |
561 | let old_parent = self.parent; |
562 | self.resolver.build_reduced_graph_for_item(item, &mut self.parent); | |
92a42be0 | 563 | intravisit::walk_item(self, item); |
1a4d82fc JJ |
564 | self.parent = old_parent; |
565 | } | |
566 | ||
567 | fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { | |
54a0048b | 568 | self.resolver.build_reduced_graph_for_foreign_item(foreign_item, &self.parent); |
1a4d82fc JJ |
569 | } |
570 | ||
1a4d82fc | 571 | fn visit_block(&mut self, block: &Block) { |
54a0048b SL |
572 | let old_parent = self.parent; |
573 | self.resolver.build_reduced_graph_for_block(block, &mut self.parent); | |
92a42be0 | 574 | intravisit::walk_block(self, block); |
1a4d82fc JJ |
575 | self.parent = old_parent; |
576 | } | |
577 | } |