]> git.lizzy.rs Git - rust.git/blob - src/librustc_resolve/build_reduced_graph.rs
Rollup merge of #31352 - steveklabnik:gh31154, r=nikomatsakis
[rust.git] / src / librustc_resolve / build_reduced_graph.rs
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
16 use DefModifiers;
17 use resolve_imports::ImportDirective;
18 use resolve_imports::ImportDirectiveSubclass::{self, SingleImport, GlobImport};
19 use resolve_imports::ImportResolution;
20 use Module;
21 use Namespace::{self, TypeNS, ValueNS};
22 use {NameBinding, DefOrModule};
23 use {names_to_string, module_to_string};
24 use ParentLink::{ModuleParentLink, BlockParentLink};
25 use Resolver;
26 use resolve_imports::Shadowable;
27 use {resolve_error, resolve_struct_error, ResolutionError};
28
29 use rustc::middle::cstore::{CrateStore, ChildItem, DlDef, DlField, DlImpl};
30 use rustc::middle::def::*;
31 use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId};
32 use rustc::middle::ty::VariantKind;
33
34 use syntax::ast::{Name, NodeId};
35 use syntax::attr::AttrMetaMethods;
36 use syntax::parse::token::special_idents;
37 use syntax::codemap::{Span, DUMMY_SP};
38
39 use rustc_front::hir;
40 use rustc_front::hir::{Block, DeclItem};
41 use rustc_front::hir::{ForeignItem, ForeignItemFn, ForeignItemStatic};
42 use rustc_front::hir::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
43 use rustc_front::hir::{ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
44 use rustc_front::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
45 use rustc_front::hir::{NamedField, PathListIdent, PathListMod};
46 use rustc_front::hir::StmtDecl;
47 use rustc_front::hir::UnnamedField;
48 use rustc_front::hir::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
49 use rustc_front::hir::Visibility;
50 use rustc_front::intravisit::{self, Visitor};
51
52 use std::mem::replace;
53 use std::ops::{Deref, DerefMut};
54
55 struct GraphBuilder<'a, 'b: 'a, 'tcx: 'b> {
56     resolver: &'a mut Resolver<'b, 'tcx>,
57 }
58
59 impl<'a, 'b:'a, 'tcx:'b> Deref for GraphBuilder<'a, 'b, 'tcx> {
60     type Target = Resolver<'b, 'tcx>;
61
62     fn deref(&self) -> &Resolver<'b, 'tcx> {
63         &*self.resolver
64     }
65 }
66
67 impl<'a, 'b:'a, 'tcx:'b> DerefMut for GraphBuilder<'a, 'b, 'tcx> {
68     fn deref_mut(&mut self) -> &mut Resolver<'b, 'tcx> {
69         &mut *self.resolver
70     }
71 }
72
73 trait ToNameBinding<'a> {
74     fn to_name_binding(self) -> NameBinding<'a>;
75 }
76
77 impl<'a> ToNameBinding<'a> for (Module<'a>, Span) {
78     fn to_name_binding(self) -> NameBinding<'a> {
79         NameBinding::create_from_module(self.0, Some(self.1))
80     }
81 }
82
83 impl<'a> ToNameBinding<'a> for (Def, Span, DefModifiers) {
84     fn to_name_binding(self) -> NameBinding<'a> {
85         let def = DefOrModule::Def(self.0);
86         NameBinding { modifiers: self.2, def_or_module: def, span: Some(self.1) }
87     }
88 }
89
90 impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
91     /// Constructs the reduced graph for the entire crate.
92     fn build_reduced_graph(self, krate: &hir::Crate) {
93         let mut visitor = BuildReducedGraphVisitor {
94             parent: self.graph_root,
95             builder: self,
96         };
97         intravisit::walk_crate(&mut visitor, krate);
98     }
99
100     /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined.
101     fn try_define<T>(&self, parent: Module<'b>, name: Name, ns: Namespace, def: T)
102         where T: ToNameBinding<'b>
103     {
104         parent.try_define_child(name, ns, def.to_name_binding());
105     }
106
107     /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
108     /// otherwise, reports an error.
109     fn define<T: ToNameBinding<'b>>(&self, parent: Module<'b>, name: Name, ns: Namespace, def: T) {
110         let binding = def.to_name_binding();
111         let old_binding = match parent.try_define_child(name, ns, binding.clone()) {
112             Some(old_binding) => old_binding,
113             None => return,
114         };
115
116         let span = binding.span.unwrap_or(DUMMY_SP);
117         if !old_binding.is_extern_crate() && !binding.is_extern_crate() {
118             // Record an error here by looking up the namespace that had the duplicate
119             let ns_str = match ns { TypeNS => "type or module", ValueNS => "value" };
120             let resolution_error = ResolutionError::DuplicateDefinition(ns_str, name);
121             let mut err = resolve_struct_error(self, span, resolution_error);
122
123             if let Some(sp) = old_binding.span {
124                 let note = format!("first definition of {} `{}` here", ns_str, name);
125                 err.span_note(sp, &note);
126             }
127             err.emit();
128         } else if old_binding.is_extern_crate() && binding.is_extern_crate() {
129             span_err!(self.session,
130                       span,
131                       E0259,
132                       "an external crate named `{}` has already been imported into this module",
133                       name);
134         } else {
135             span_err!(self.session,
136                       span,
137                       E0260,
138                       "the name `{}` conflicts with an external crate \
139                       that has been imported into this module",
140                       name);
141         }
142     }
143
144     fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
145         // Check each statement.
146         for statement in &block.stmts {
147             match statement.node {
148                 StmtDecl(ref declaration, _) => {
149                     match declaration.node {
150                         DeclItem(_) => {
151                             return true;
152                         }
153                         _ => {
154                             // Keep searching.
155                         }
156                     }
157                 }
158                 _ => {
159                     // Keep searching.
160                 }
161             }
162         }
163
164         // If we found no items, we don't need to create
165         // an anonymous module.
166
167         return false;
168     }
169
170     /// Constructs the reduced graph for one item.
171     fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> Module<'b> {
172         let name = item.name;
173         let sp = item.span;
174         let is_public = item.vis == hir::Public;
175         let modifiers = if is_public {
176             DefModifiers::PUBLIC
177         } else {
178             DefModifiers::empty()
179         } | DefModifiers::IMPORTABLE;
180
181         match item.node {
182             ItemUse(ref view_path) => {
183                 // Extract and intern the module part of the path. For
184                 // globs and lists, the path is found directly in the AST;
185                 // for simple paths we have to munge the path a little.
186                 let module_path = match view_path.node {
187                     ViewPathSimple(_, ref full_path) => {
188                         full_path.segments
189                                  .split_last()
190                                  .unwrap()
191                                  .1
192                                  .iter()
193                                  .map(|seg| seg.identifier.name)
194                                  .collect()
195                     }
196
197                     ViewPathGlob(ref module_ident_path) |
198                     ViewPathList(ref module_ident_path, _) => {
199                         module_ident_path.segments
200                                          .iter()
201                                          .map(|seg| seg.identifier.name)
202                                          .collect()
203                     }
204                 };
205
206                 // Build up the import directives.
207                 let shadowable = item.attrs.iter().any(|attr| {
208                     attr.name() == special_idents::prelude_import.name.as_str()
209                 });
210                 let shadowable = if shadowable {
211                     Shadowable::Always
212                 } else {
213                     Shadowable::Never
214                 };
215
216                 match view_path.node {
217                     ViewPathSimple(binding, ref full_path) => {
218                         let source_name = full_path.segments.last().unwrap().identifier.name;
219                         if source_name.as_str() == "mod" || source_name.as_str() == "self" {
220                             resolve_error(self,
221                                           view_path.span,
222                                           ResolutionError::SelfImportsOnlyAllowedWithin);
223                         }
224
225                         let subclass = SingleImport(binding, source_name);
226                         self.build_import_directive(parent,
227                                                     module_path,
228                                                     subclass,
229                                                     view_path.span,
230                                                     item.id,
231                                                     is_public,
232                                                     shadowable);
233                     }
234                     ViewPathList(_, ref source_items) => {
235                         // Make sure there's at most one `mod` import in the list.
236                         let mod_spans = source_items.iter()
237                                                     .filter_map(|item| {
238                                                         match item.node {
239                                                             PathListMod { .. } => Some(item.span),
240                                                             _ => None,
241                                                         }
242                                                     })
243                                                     .collect::<Vec<Span>>();
244                         if mod_spans.len() > 1 {
245                             let mut e = resolve_struct_error(self,
246                                           mod_spans[0],
247                                           ResolutionError::SelfImportCanOnlyAppearOnceInTheList);
248                             for other_span in mod_spans.iter().skip(1) {
249                                 e.span_note(*other_span, "another `self` import appears here");
250                             }
251                             e.emit();
252                         }
253
254                         for source_item in source_items {
255                             let (module_path, name, rename) = match source_item.node {
256                                 PathListIdent { name, rename, .. } =>
257                                     (module_path.clone(), name, rename.unwrap_or(name)),
258                                 PathListMod { rename, .. } => {
259                                     let name = match module_path.last() {
260                                         Some(name) => *name,
261                                         None => {
262                                             resolve_error(
263                                                 self,
264                                                 source_item.span,
265                                                 ResolutionError::
266                                                 SelfImportOnlyInImportListWithNonEmptyPrefix
267                                             );
268                                             continue;
269                                         }
270                                     };
271                                     let module_path = module_path.split_last().unwrap().1;
272                                     let rename = rename.unwrap_or(name);
273                                     (module_path.to_vec(), name, rename)
274                                 }
275                             };
276                             self.build_import_directive(parent,
277                                                         module_path,
278                                                         SingleImport(rename, name),
279                                                         source_item.span,
280                                                         source_item.node.id(),
281                                                         is_public,
282                                                         shadowable);
283                         }
284                     }
285                     ViewPathGlob(_) => {
286                         self.build_import_directive(parent,
287                                                     module_path,
288                                                     GlobImport,
289                                                     view_path.span,
290                                                     item.id,
291                                                     is_public,
292                                                     shadowable);
293                     }
294                 }
295                 parent
296             }
297
298             ItemExternCrate(_) => {
299                 // n.b. we don't need to look at the path option here, because cstore already
300                 // did
301                 if let Some(crate_id) = self.session.cstore.extern_mod_stmt_cnum(item.id) {
302                     let def_id = DefId {
303                         krate: crate_id,
304                         index: CRATE_DEF_INDEX,
305                     };
306                     self.external_exports.insert(def_id);
307                     let parent_link = ModuleParentLink(parent, name);
308                     let def = Def::Mod(def_id);
309                     let external_module = self.new_extern_crate_module(parent_link, def);
310                     self.define(parent, name, TypeNS, (external_module, sp));
311
312                     self.build_reduced_graph_for_external_crate(&external_module);
313                 }
314                 parent
315             }
316
317             ItemMod(..) => {
318                 let parent_link = ModuleParentLink(parent, name);
319                 let def = Def::Mod(self.ast_map.local_def_id(item.id));
320                 let module = self.new_module(parent_link, Some(def), false, is_public);
321                 self.define(parent, name, TypeNS, (module, sp));
322                 module
323             }
324
325             ItemForeignMod(..) => parent,
326
327             // These items live in the value namespace.
328             ItemStatic(_, m, _) => {
329                 let mutbl = m == hir::MutMutable;
330                 let def = Def::Static(self.ast_map.local_def_id(item.id), mutbl);
331                 self.define(parent, name, ValueNS, (def, sp, modifiers));
332                 parent
333             }
334             ItemConst(_, _) => {
335                 let def = Def::Const(self.ast_map.local_def_id(item.id));
336                 self.define(parent, name, ValueNS, (def, sp, modifiers));
337                 parent
338             }
339             ItemFn(_, _, _, _, _, _) => {
340                 let def = Def::Fn(self.ast_map.local_def_id(item.id));
341                 self.define(parent, name, ValueNS, (def, sp, modifiers));
342                 parent
343             }
344
345             // These items live in the type namespace.
346             ItemTy(..) => {
347                 let parent_link = ModuleParentLink(parent, name);
348                 let def = Def::TyAlias(self.ast_map.local_def_id(item.id));
349                 let module = self.new_module(parent_link, Some(def), false, is_public);
350                 self.define(parent, name, TypeNS, (module, sp));
351                 parent
352             }
353
354             ItemEnum(ref enum_definition, _) => {
355                 let parent_link = ModuleParentLink(parent, name);
356                 let def = Def::Enum(self.ast_map.local_def_id(item.id));
357                 let module = self.new_module(parent_link, Some(def), false, is_public);
358                 self.define(parent, name, TypeNS, (module, sp));
359
360                 let variant_modifiers = if is_public {
361                     DefModifiers::empty()
362                 } else {
363                     DefModifiers::PRIVATE_VARIANT
364                 };
365                 for variant in &(*enum_definition).variants {
366                     let item_def_id = self.ast_map.local_def_id(item.id);
367                     self.build_reduced_graph_for_variant(variant, item_def_id,
368                                                          &module, variant_modifiers);
369                 }
370                 parent
371             }
372
373             // These items live in both the type and value namespaces.
374             ItemStruct(ref struct_def, _) => {
375                 // Define a name in the type namespace.
376                 let def = Def::Struct(self.ast_map.local_def_id(item.id));
377                 self.define(parent, name, TypeNS, (def, sp, modifiers));
378
379                 // If this is a newtype or unit-like struct, define a name
380                 // in the value namespace as well
381                 if !struct_def.is_struct() {
382                     let def = Def::Struct(self.ast_map.local_def_id(struct_def.id()));
383                     self.define(parent, name, ValueNS, (def, sp, modifiers));
384                 }
385
386                 // Record the def ID and fields of this struct.
387                 let named_fields = struct_def.fields()
388                                              .iter()
389                                              .filter_map(|f| {
390                                                  match f.node.kind {
391                                                      NamedField(name, _) => Some(name),
392                                                      UnnamedField(_) => None,
393                                                  }
394                                              })
395                                              .collect();
396                 let item_def_id = self.ast_map.local_def_id(item.id);
397                 self.structs.insert(item_def_id, named_fields);
398
399                 parent
400             }
401
402             ItemDefaultImpl(_, _) |
403             ItemImpl(..) => parent,
404
405             ItemTrait(_, _, _, ref items) => {
406                 let def_id = self.ast_map.local_def_id(item.id);
407
408                 // Add all the items within to a new module.
409                 let parent_link = ModuleParentLink(parent, name);
410                 let def = Def::Trait(def_id);
411                 let module_parent = self.new_module(parent_link, Some(def), false, is_public);
412                 self.define(parent, name, TypeNS, (module_parent, sp));
413
414                 // Add the names of all the items to the trait info.
415                 for item in items {
416                     let item_def_id = self.ast_map.local_def_id(item.id);
417                     let (def, ns) = match item.node {
418                         hir::ConstTraitItem(..) => (Def::AssociatedConst(item_def_id), ValueNS),
419                         hir::MethodTraitItem(..) => (Def::Method(item_def_id), ValueNS),
420                         hir::TypeTraitItem(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
421                     };
422
423                     let modifiers = DefModifiers::PUBLIC; // NB: not DefModifiers::IMPORTABLE
424                     self.define(&module_parent, item.name, ns, (def, item.span, modifiers));
425
426                     self.trait_item_map.insert((item.name, def_id), item_def_id);
427                 }
428
429                 parent
430             }
431         }
432     }
433
434     // Constructs the reduced graph for one variant. Variants exist in the
435     // type and value namespaces.
436     fn build_reduced_graph_for_variant(&mut self,
437                                        variant: &Variant,
438                                        item_id: DefId,
439                                        parent: Module<'b>,
440                                        variant_modifiers: DefModifiers) {
441         let name = variant.node.name;
442         if variant.node.data.is_struct() {
443             // Not adding fields for variants as they are not accessed with a self receiver
444             let variant_def_id = self.ast_map.local_def_id(variant.node.data.id());
445             self.structs.insert(variant_def_id, Vec::new());
446         }
447
448         // Variants are always treated as importable to allow them to be glob used.
449         // All variants are defined in both type and value namespaces as future-proofing.
450         let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE | variant_modifiers;
451         let def = Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id()));
452
453         self.define(parent, name, ValueNS, (def, variant.span, modifiers));
454         self.define(parent, name, TypeNS, (def, variant.span, modifiers));
455     }
456
457     /// Constructs the reduced graph for one foreign item.
458     fn build_reduced_graph_for_foreign_item(&mut self,
459                                             foreign_item: &ForeignItem,
460                                             parent: Module<'b>) {
461         let name = foreign_item.name;
462         let is_public = foreign_item.vis == hir::Public;
463         let modifiers = if is_public {
464             DefModifiers::PUBLIC
465         } else {
466             DefModifiers::empty()
467         } | DefModifiers::IMPORTABLE;
468
469         let def = match foreign_item.node {
470             ForeignItemFn(..) => {
471                 Def::Fn(self.ast_map.local_def_id(foreign_item.id))
472             }
473             ForeignItemStatic(_, m) => {
474                 Def::Static(self.ast_map.local_def_id(foreign_item.id), m)
475             }
476         };
477         self.define(parent, name, ValueNS, (def, foreign_item.span, modifiers));
478     }
479
480     fn build_reduced_graph_for_block(&mut self, block: &Block, parent: Module<'b>) -> Module<'b> {
481         if self.block_needs_anonymous_module(block) {
482             let block_id = block.id;
483
484             debug!("(building reduced graph for block) creating a new anonymous module for block \
485                     {}",
486                    block_id);
487
488             let parent_link = BlockParentLink(parent, block_id);
489             let new_module = self.new_module(parent_link, None, false, false);
490             parent.anonymous_children.borrow_mut().insert(block_id, new_module);
491             new_module
492         } else {
493             parent
494         }
495     }
496
497     fn handle_external_def(&mut self,
498                            def: Def,
499                            vis: Visibility,
500                            final_ident: &str,
501                            name: Name,
502                            new_parent: Module<'b>) {
503         debug!("(building reduced graph for external crate) building external def {}, priv {:?}",
504                final_ident,
505                vis);
506         let is_public = vis == hir::Public;
507
508         let mut modifiers = DefModifiers::empty();
509         if is_public {
510             modifiers = modifiers | DefModifiers::PUBLIC;
511         }
512         if new_parent.is_normal() {
513             modifiers = modifiers | DefModifiers::IMPORTABLE;
514         }
515
516         let is_exported = is_public &&
517                           match new_parent.def_id() {
518             None => true,
519             Some(did) => self.external_exports.contains(&did),
520         };
521         if is_exported {
522             self.external_exports.insert(def.def_id());
523         }
524
525         match def {
526             Def::Mod(_) | Def::ForeignMod(_) | Def::Enum(..) | Def::TyAlias(..) => {
527                 debug!("(building reduced graph for external crate) building module {} {}",
528                        final_ident,
529                        is_public);
530                 let parent_link = ModuleParentLink(new_parent, name);
531                 let module = self.new_module(parent_link, Some(def), true, is_public);
532                 self.try_define(new_parent, name, TypeNS, (module, DUMMY_SP));
533             }
534             Def::Variant(_, variant_id) => {
535                 debug!("(building reduced graph for external crate) building variant {}",
536                        final_ident);
537                 // Variants are always treated as importable to allow them to be glob used.
538                 // All variants are defined in both type and value namespaces as future-proofing.
539                 let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE;
540                 self.try_define(new_parent, name, TypeNS, (def, DUMMY_SP, modifiers));
541                 self.try_define(new_parent, name, ValueNS, (def, DUMMY_SP, modifiers));
542                 if self.session.cstore.variant_kind(variant_id) == Some(VariantKind::Struct) {
543                     // Not adding fields for variants as they are not accessed with a self receiver
544                     self.structs.insert(variant_id, Vec::new());
545                 }
546             }
547             Def::Fn(..) |
548             Def::Static(..) |
549             Def::Const(..) |
550             Def::AssociatedConst(..) |
551             Def::Method(..) => {
552                 debug!("(building reduced graph for external crate) building value (fn/static) {}",
553                        final_ident);
554                 self.try_define(new_parent, name, ValueNS, (def, DUMMY_SP, modifiers));
555             }
556             Def::Trait(def_id) => {
557                 debug!("(building reduced graph for external crate) building type {}",
558                        final_ident);
559
560                 // If this is a trait, add all the trait item names to the trait
561                 // info.
562
563                 let trait_item_def_ids = self.session.cstore.trait_item_def_ids(def_id);
564                 for trait_item_def in &trait_item_def_ids {
565                     let trait_item_name =
566                         self.session.cstore.item_name(trait_item_def.def_id());
567
568                     debug!("(building reduced graph for external crate) ... adding trait item \
569                             '{}'",
570                            trait_item_name);
571
572                     self.trait_item_map.insert((trait_item_name, def_id), trait_item_def.def_id());
573
574                     if is_exported {
575                         self.external_exports.insert(trait_item_def.def_id());
576                     }
577                 }
578
579                 let parent_link = ModuleParentLink(new_parent, name);
580                 let module = self.new_module(parent_link, Some(def), true, is_public);
581                 self.try_define(new_parent, name, TypeNS, (module, DUMMY_SP));
582             }
583             Def::AssociatedTy(..) => {
584                 debug!("(building reduced graph for external crate) building type {}",
585                        final_ident);
586                 self.try_define(new_parent, name, TypeNS, (def, DUMMY_SP, modifiers));
587             }
588             Def::Struct(def_id)
589                 if self.session.cstore.tuple_struct_definition_if_ctor(def_id).is_none() => {
590                 debug!("(building reduced graph for external crate) building type and value for \
591                         {}",
592                        final_ident);
593                 self.try_define(new_parent, name, TypeNS, (def, DUMMY_SP, modifiers));
594                 if let Some(ctor_def_id) = self.session.cstore.struct_ctor_def_id(def_id) {
595                     let def = Def::Struct(ctor_def_id);
596                     self.try_define(new_parent, name, ValueNS, (def, DUMMY_SP, modifiers));
597                 }
598
599                 // Record the def ID and fields of this struct.
600                 let fields = self.session.cstore.struct_field_names(def_id);
601                 self.structs.insert(def_id, fields);
602             }
603             Def::Struct(..) => {}
604             Def::Local(..) |
605             Def::PrimTy(..) |
606             Def::TyParam(..) |
607             Def::Upvar(..) |
608             Def::Label(..) |
609             Def::SelfTy(..) |
610             Def::Err => {
611                 panic!("didn't expect `{:?}`", def);
612             }
613         }
614     }
615
616     /// Builds the reduced graph for a single item in an external crate.
617     fn build_reduced_graph_for_external_crate_def(&mut self,
618                                                   root: Module<'b>,
619                                                   xcdef: ChildItem) {
620         match xcdef.def {
621             DlDef(def) => {
622                 // Add the new child item, if necessary.
623                 match def {
624                     Def::ForeignMod(def_id) => {
625                         // Foreign modules have no names. Recur and populate
626                         // eagerly.
627                         for child in self.session.cstore.item_children(def_id) {
628                             self.build_reduced_graph_for_external_crate_def(root, child)
629                         }
630                     }
631                     _ => {
632                         self.handle_external_def(def,
633                                                  xcdef.vis,
634                                                  &xcdef.name.as_str(),
635                                                  xcdef.name,
636                                                  root);
637                     }
638                 }
639             }
640             DlImpl(_) => {
641                 debug!("(building reduced graph for external crate) ignoring impl");
642             }
643             DlField => {
644                 debug!("(building reduced graph for external crate) ignoring field");
645             }
646         }
647     }
648
649     /// Builds the reduced graph rooted at the given external module.
650     fn populate_external_module(&mut self, module: Module<'b>) {
651         debug!("(populating external module) attempting to populate {}",
652                module_to_string(module));
653
654         let def_id = match module.def_id() {
655             None => {
656                 debug!("(populating external module) ... no def ID!");
657                 return;
658             }
659             Some(def_id) => def_id,
660         };
661
662         for child in self.session.cstore.item_children(def_id) {
663             debug!("(populating external module) ... found ident: {}",
664                    child.name);
665             self.build_reduced_graph_for_external_crate_def(module, child);
666         }
667         module.populated.set(true)
668     }
669
670     /// Ensures that the reduced graph rooted at the given external module
671     /// is built, building it if it is not.
672     fn populate_module_if_necessary(&mut self, module: Module<'b>) {
673         if !module.populated.get() {
674             self.populate_external_module(module)
675         }
676         assert!(module.populated.get())
677     }
678
679     /// Builds the reduced graph rooted at the 'use' directive for an external
680     /// crate.
681     fn build_reduced_graph_for_external_crate(&mut self, root: Module<'b>) {
682         let root_cnum = root.def_id().unwrap().krate;
683         for child in self.session.cstore.crate_top_level_items(root_cnum) {
684             self.build_reduced_graph_for_external_crate_def(root, child);
685         }
686     }
687
688     /// Creates and adds an import directive to the given module.
689     fn build_import_directive(&mut self,
690                               module_: Module<'b>,
691                               module_path: Vec<Name>,
692                               subclass: ImportDirectiveSubclass,
693                               span: Span,
694                               id: NodeId,
695                               is_public: bool,
696                               shadowable: Shadowable) {
697         module_.imports
698                .borrow_mut()
699                .push(ImportDirective::new(module_path, subclass, span, id, is_public, shadowable));
700         self.unresolved_imports += 1;
701
702         if is_public {
703             module_.inc_pub_count();
704         }
705
706         // Bump the reference count on the name. Or, if this is a glob, set
707         // the appropriate flag.
708
709         match subclass {
710             SingleImport(target, _) => {
711                 debug!("(building import directive) building import directive: {}::{}",
712                        names_to_string(&module_.imports.borrow().last().unwrap().module_path),
713                        target);
714
715                 let mut import_resolutions = module_.import_resolutions.borrow_mut();
716                 for &ns in [TypeNS, ValueNS].iter() {
717                     let mut resolution = import_resolutions.entry((target, ns)).or_insert(
718                         ImportResolution::new(id, is_public)
719                     );
720
721                     resolution.outstanding_references += 1;
722                     // the source of this name is different now
723                     resolution.id = id;
724                     resolution.is_public = is_public;
725                 }
726             }
727             GlobImport => {
728                 // Set the glob flag. This tells us that we don't know the
729                 // module's exports ahead of time.
730
731                 module_.inc_glob_count();
732                 if is_public {
733                     module_.inc_pub_glob_count();
734                 }
735             }
736         }
737     }
738 }
739
740 struct BuildReducedGraphVisitor<'a, 'b: 'a, 'tcx: 'b> {
741     builder: GraphBuilder<'a, 'b, 'tcx>,
742     parent: Module<'b>,
743 }
744
745 impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
746     fn visit_nested_item(&mut self, item: hir::ItemId) {
747         self.visit_item(self.builder.resolver.ast_map.expect_item(item.id))
748     }
749
750     fn visit_item(&mut self, item: &Item) {
751         let p = self.builder.build_reduced_graph_for_item(item, &self.parent);
752         let old_parent = replace(&mut self.parent, p);
753         intravisit::walk_item(self, item);
754         self.parent = old_parent;
755     }
756
757     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
758         self.builder.build_reduced_graph_for_foreign_item(foreign_item, &self.parent);
759     }
760
761     fn visit_block(&mut self, block: &Block) {
762         let np = self.builder.build_reduced_graph_for_block(block, &self.parent);
763         let old_parent = replace(&mut self.parent, np);
764         intravisit::walk_block(self, block);
765         self.parent = old_parent;
766     }
767 }
768
769 pub fn build_reduced_graph(resolver: &mut Resolver, krate: &hir::Crate) {
770     GraphBuilder { resolver: resolver }.build_reduced_graph(krate);
771 }
772
773 pub fn populate_module_if_necessary<'a, 'tcx>(resolver: &mut Resolver<'a, 'tcx>,
774                                               module: Module<'a>) {
775     GraphBuilder { resolver: resolver }.populate_module_if_necessary(module);
776 }