]> git.lizzy.rs Git - rust.git/blob - src/librustc_resolve/build_reduced_graph.rs
c50cb5960b1ff89a517fefaed3b7a0aa8ae09ad9
[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 ModuleKind::*;
22 use Namespace::{TypeNS, ValueNS};
23 use NameBindings;
24 use {names_to_string, module_to_string};
25 use ParentLink::{self, ModuleParentLink, BlockParentLink};
26 use Resolver;
27 use resolve_imports::Shadowable;
28 use TypeNsDef;
29 use {resolve_error, ResolutionError};
30
31 use self::DuplicateCheckingMode::*;
32 use self::NamespaceError::*;
33
34 use rustc::metadata::csearch;
35 use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
36 use rustc::middle::def::*;
37 use rustc::middle::def_id::DefId;
38
39 use syntax::ast::{Name, NodeId};
40 use syntax::attr::AttrMetaMethods;
41 use syntax::parse::token::special_idents;
42 use syntax::codemap::{Span, DUMMY_SP};
43
44 use rustc_front::hir;
45 use rustc_front::hir::{Block, Crate, DeclItem};
46 use rustc_front::hir::{ForeignItem, ForeignItemFn, ForeignItemStatic};
47 use rustc_front::hir::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
48 use rustc_front::hir::{ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
49 use rustc_front::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
50 use rustc_front::hir::{NamedField, PathListIdent, PathListMod, Public};
51 use rustc_front::hir::StmtDecl;
52 use rustc_front::hir::StructVariantKind;
53 use rustc_front::hir::TupleVariantKind;
54 use rustc_front::hir::UnnamedField;
55 use rustc_front::hir::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
56 use rustc_front::hir::Visibility;
57 use rustc_front::visit::{self, Visitor};
58
59 use std::mem::replace;
60 use std::ops::{Deref, DerefMut};
61 use std::rc::Rc;
62
63 // Specifies how duplicates should be handled when adding a child item if
64 // another item exists with the same name in some namespace.
65 #[derive(Copy, Clone, PartialEq)]
66 enum DuplicateCheckingMode {
67     ForbidDuplicateModules,
68     ForbidDuplicateTypesAndModules,
69     ForbidDuplicateValues,
70     ForbidDuplicateTypesAndValues,
71     OverwriteDuplicates
72 }
73
74 #[derive(Copy, Clone, PartialEq)]
75 enum NamespaceError {
76     NoError,
77     ModuleError,
78     TypeError,
79     ValueError
80 }
81
82 fn namespace_error_to_string(ns: NamespaceError) -> &'static str {
83     match ns {
84         NoError                 => "",
85         ModuleError | TypeError => "type or module",
86         ValueError              => "value",
87     }
88 }
89
90 struct GraphBuilder<'a, 'b:'a, 'tcx:'b> {
91     resolver: &'a mut Resolver<'b, 'tcx>
92 }
93
94 impl<'a, 'b:'a, 'tcx:'b> Deref for GraphBuilder<'a, 'b, 'tcx> {
95     type Target = Resolver<'b, 'tcx>;
96
97     fn deref(&self) -> &Resolver<'b, 'tcx> {
98         &*self.resolver
99     }
100 }
101
102 impl<'a, 'b:'a, 'tcx:'b> DerefMut for GraphBuilder<'a, 'b, 'tcx> {
103     fn deref_mut(&mut self) -> &mut Resolver<'b, 'tcx> {
104         &mut *self.resolver
105     }
106 }
107
108 impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
109     /// Constructs the reduced graph for the entire crate.
110     fn build_reduced_graph(self, krate: &hir::Crate) {
111         let parent = self.graph_root.get_module();
112         let mut visitor = BuildReducedGraphVisitor {
113             builder: self,
114             parent: parent
115         };
116         visit::walk_crate(&mut visitor, krate);
117     }
118
119     /// Adds a new child item to the module definition of the parent node and
120     /// returns its corresponding name bindings as well as the current parent.
121     /// Or, if we're inside a block, creates (or reuses) an anonymous module
122     /// corresponding to the innermost block ID and returns the name bindings
123     /// as well as the newly-created parent.
124     ///
125     /// # Panics
126     ///
127     /// Panics if this node does not have a module definition and we are not inside
128     /// a block.
129     fn add_child(&self,
130                  name: Name,
131                  parent: &Rc<Module>,
132                  duplicate_checking_mode: DuplicateCheckingMode,
133                  // For printing errors
134                  sp: Span)
135                  -> Rc<NameBindings> {
136         // If this is the immediate descendant of a module, then we add the
137         // child name directly. Otherwise, we create or reuse an anonymous
138         // module and add the child to that.
139
140         self.check_for_conflicts_between_external_crates_and_items(&**parent,
141                                                                    name,
142                                                                    sp);
143
144         // Add or reuse the child.
145         let child = parent.children.borrow().get(&name).cloned();
146         match child {
147             None => {
148                 let child = Rc::new(NameBindings::new());
149                 parent.children.borrow_mut().insert(name, child.clone());
150                 child
151             }
152             Some(child) => {
153                 // Enforce the duplicate checking mode:
154                 //
155                 // * If we're requesting duplicate module checking, check that
156                 //   there isn't a module in the module with the same name.
157                 //
158                 // * If we're requesting duplicate type checking, check that
159                 //   there isn't a type in the module with the same name.
160                 //
161                 // * If we're requesting duplicate value checking, check that
162                 //   there isn't a value in the module with the same name.
163                 //
164                 // * If we're requesting duplicate type checking and duplicate
165                 //   value checking, check that there isn't a duplicate type
166                 //   and a duplicate value with the same name.
167                 //
168                 // * If no duplicate checking was requested at all, do
169                 //   nothing.
170
171                 let mut duplicate_type = NoError;
172                 let ns = match duplicate_checking_mode {
173                     ForbidDuplicateModules => {
174                         if child.get_module_if_available().is_some() {
175                             duplicate_type = ModuleError;
176                         }
177                         Some(TypeNS)
178                     }
179                     ForbidDuplicateTypesAndModules => {
180                         if child.defined_in_namespace(TypeNS) {
181                             duplicate_type = TypeError;
182                         }
183                         Some(TypeNS)
184                     }
185                     ForbidDuplicateValues => {
186                         if child.defined_in_namespace(ValueNS) {
187                             duplicate_type = ValueError;
188                         }
189                         Some(ValueNS)
190                     }
191                     ForbidDuplicateTypesAndValues => {
192                         let mut n = None;
193                         match child.def_for_namespace(TypeNS) {
194                             Some(DefMod(_)) | None => {}
195                             Some(_) => {
196                                 n = Some(TypeNS);
197                                 duplicate_type = TypeError;
198                             }
199                         };
200                         if child.defined_in_namespace(ValueNS) {
201                             duplicate_type = ValueError;
202                             n = Some(ValueNS);
203                         }
204                         n
205                     }
206                     OverwriteDuplicates => None
207                 };
208                 if duplicate_type != NoError {
209                     // Return an error here by looking up the namespace that
210                     // had the duplicate.
211                     let ns = ns.unwrap();
212                     resolve_error(
213                         self,
214                         sp,
215                         ResolutionError::DuplicateDefinition(
216                             namespace_error_to_string(duplicate_type),
217                             name)
218                     );
219                     {
220                         let r = child.span_for_namespace(ns);
221                         if let Some(sp) = r {
222                             self.session.span_note(sp,
223                                  &format!("first definition of {} `{}` here",
224                                       namespace_error_to_string(duplicate_type),
225                                       name));
226                         }
227                     }
228                 }
229                 child
230             }
231         }
232     }
233
234     fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
235         // Check each statement.
236         for statement in &block.stmts {
237             match statement.node {
238                 StmtDecl(ref declaration, _) => {
239                     match declaration.node {
240                         DeclItem(_) => {
241                             return true;
242                         }
243                         _ => {
244                             // Keep searching.
245                         }
246                     }
247                 }
248                 _ => {
249                     // Keep searching.
250                 }
251             }
252         }
253
254         // If we found no items, we don't need to create
255         // an anonymous module.
256
257         return false;
258     }
259
260     fn get_parent_link(&mut self, parent: &Rc<Module>, name: Name) -> ParentLink {
261         ModuleParentLink(Rc::downgrade(parent), name)
262     }
263
264     /// Constructs the reduced graph for one item.
265     fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) -> Rc<Module> {
266         let name = item.name;
267         let sp = item.span;
268         let is_public = item.vis == hir::Public;
269         let modifiers = if is_public {
270             DefModifiers::PUBLIC
271         } else {
272             DefModifiers::empty()
273         } | DefModifiers::IMPORTABLE;
274
275         match item.node {
276             ItemUse(ref view_path) => {
277                 // Extract and intern the module part of the path. For
278                 // globs and lists, the path is found directly in the AST;
279                 // for simple paths we have to munge the path a little.
280                 let module_path = match view_path.node {
281                     ViewPathSimple(_, ref full_path) => {
282                         full_path.segments
283                             .split_last().unwrap().1
284                             .iter().map(|seg| seg.identifier.name)
285                             .collect()
286                     }
287
288                     ViewPathGlob(ref module_ident_path) |
289                     ViewPathList(ref module_ident_path, _) => {
290                         module_ident_path.segments
291                             .iter().map(|seg| seg.identifier.name).collect()
292                     }
293                 };
294
295                 // Build up the import directives.
296                 let shadowable = item.attrs.iter().any(|attr| {
297                     attr.name() == special_idents::prelude_import.name.as_str()
298                 });
299                 let shadowable = if shadowable {
300                     Shadowable::Always
301                 } else {
302                     Shadowable::Never
303                 };
304
305                 match view_path.node {
306                     ViewPathSimple(binding, ref full_path) => {
307                         let source_name =
308                             full_path.segments.last().unwrap().identifier.name;
309                         if source_name.as_str() == "mod" || source_name.as_str() == "self" {
310                             resolve_error(self,
311                                           view_path.span,
312                                           ResolutionError::SelfImportsOnlyAllowedWithin);
313                         }
314
315                         let subclass = SingleImport(binding, source_name);
316                         self.build_import_directive(&**parent,
317                                                     module_path,
318                                                     subclass,
319                                                     view_path.span,
320                                                     item.id,
321                                                     is_public,
322                                                     shadowable);
323                     }
324                     ViewPathList(_, ref source_items) => {
325                         // Make sure there's at most one `mod` import in the list.
326                         let mod_spans = source_items.iter().filter_map(|item| match item.node {
327                             PathListMod { .. } => Some(item.span),
328                             _ => None
329                         }).collect::<Vec<Span>>();
330                         if mod_spans.len() > 1 {
331                             resolve_error(
332                                 self,
333                                 mod_spans[0],
334                                 ResolutionError::SelfImportCanOnlyAppearOnceInTheList
335                             );
336                             for other_span in mod_spans.iter().skip(1) {
337                                 self.session.span_note(*other_span,
338                                     "another `self` import appears here");
339                             }
340                         }
341
342                         for source_item in source_items {
343                             let (module_path, name, rename) = match source_item.node {
344                                 PathListIdent { name, rename, .. } =>
345                                     (module_path.clone(), name, rename.unwrap_or(name)),
346                                 PathListMod { rename, .. } => {
347                                     let name = match module_path.last() {
348                                         Some(name) => *name,
349                                         None => {
350                                             resolve_error(
351                                                 self,
352                                                 source_item.span,
353                                                 ResolutionError::
354                                                 SelfImportOnlyInImportListWithNonEmptyPrefix
355                                             );
356                                             continue;
357                                         }
358                                     };
359                                     let module_path = module_path.split_last().unwrap().1;
360                                     let rename = rename.unwrap_or(name);
361                                     (module_path.to_vec(), name, rename)
362                                 }
363                             };
364                             self.build_import_directive(
365                                 &**parent,
366                                 module_path,
367                                 SingleImport(rename, name),
368                                 source_item.span,
369                                 source_item.node.id(),
370                                 is_public,
371                                 shadowable);
372                         }
373                     }
374                     ViewPathGlob(_) => {
375                         self.build_import_directive(&**parent,
376                                                     module_path,
377                                                     GlobImport,
378                                                     view_path.span,
379                                                     item.id,
380                                                     is_public,
381                                                     shadowable);
382                     }
383                 }
384                 parent.clone()
385             }
386
387             ItemExternCrate(_) => {
388                 // n.b. we don't need to look at the path option here, because cstore already did
389                 if let Some(crate_id) = self.session.cstore.find_extern_mod_stmt_cnum(item.id) {
390                     let def_id = DefId { krate: crate_id, xxx_node: 0 };
391                     self.external_exports.insert(def_id);
392                     let parent_link = ModuleParentLink(Rc::downgrade(parent), name);
393                     let external_module = Rc::new(Module::new(parent_link,
394                                                               Some(def_id),
395                                                               NormalModuleKind,
396                                                               false,
397                                                               true));
398                     debug!("(build reduced graph for item) found extern `{}`",
399                             module_to_string(&*external_module));
400                     self.check_for_conflicts_between_external_crates(&**parent, name, sp);
401                     parent.external_module_children.borrow_mut()
402                           .insert(name, external_module.clone());
403                     self.build_reduced_graph_for_external_crate(&external_module);
404                 }
405                 parent.clone()
406             }
407
408             ItemMod(..) => {
409                 let name_bindings = self.add_child(name, parent, ForbidDuplicateModules, sp);
410
411                 let parent_link = self.get_parent_link(parent, name);
412                 let def_id = self.ast_map.local_def_id(item.id);
413                 name_bindings.define_module(parent_link,
414                                             Some(def_id),
415                                             NormalModuleKind,
416                                             false,
417                                             is_public,
418                                             sp);
419
420                 name_bindings.get_module()
421             }
422
423             ItemForeignMod(..) => parent.clone(),
424
425             // These items live in the value namespace.
426             ItemStatic(_, m, _) => {
427                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
428                 let mutbl = m == hir::MutMutable;
429
430                 name_bindings.define_value(DefStatic(self.ast_map.local_def_id(item.id), mutbl),
431                                            sp,
432                                            modifiers);
433                 parent.clone()
434             }
435             ItemConst(_, _) => {
436                 self.add_child(name, parent, ForbidDuplicateValues, sp)
437                     .define_value(DefConst(self.ast_map.local_def_id(item.id)), sp, modifiers);
438                 parent.clone()
439             }
440             ItemFn(_, _, _, _, _, _) => {
441                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
442
443                 let def = DefFn(self.ast_map.local_def_id(item.id), false);
444                 name_bindings.define_value(def, sp, modifiers);
445                 parent.clone()
446             }
447
448             // These items live in the type namespace.
449             ItemTy(..) => {
450                 let name_bindings =
451                     self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
452
453                 name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), false), sp,
454                                           modifiers);
455
456                 let parent_link = self.get_parent_link(parent, name);
457                 name_bindings.set_module_kind(parent_link,
458                                               Some(self.ast_map.local_def_id(item.id)),
459                                               TypeModuleKind,
460                                               false,
461                                               is_public,
462                                               sp);
463                 parent.clone()
464             }
465
466             ItemEnum(ref enum_definition, _) => {
467                 let name_bindings =
468                     self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
469
470                 name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), true),
471                                           sp,
472                                           modifiers);
473
474                 let parent_link = self.get_parent_link(parent, name);
475                 name_bindings.set_module_kind(parent_link,
476                                               Some(self.ast_map.local_def_id(item.id)),
477                                               EnumModuleKind,
478                                               false,
479                                               is_public,
480                                               sp);
481
482                 let module = name_bindings.get_module();
483
484                 for variant in &(*enum_definition).variants {
485                     let item_def_id = self.ast_map.local_def_id(item.id);
486                     self.build_reduced_graph_for_variant(
487                         &**variant,
488                         item_def_id,
489                         &module);
490                 }
491                 parent.clone()
492             }
493
494             // These items live in both the type and value namespaces.
495             ItemStruct(ref struct_def, _) => {
496                 // Adding to both Type and Value namespaces or just Type?
497                 let (forbid, ctor_id) = match struct_def.ctor_id {
498                     Some(ctor_id)   => (ForbidDuplicateTypesAndValues, Some(ctor_id)),
499                     None            => (ForbidDuplicateTypesAndModules, None)
500                 };
501
502                 let name_bindings = self.add_child(name, parent, forbid, sp);
503
504                 // Define a name in the type namespace.
505                 name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), false),
506                                           sp,
507                                           modifiers);
508
509                 // If this is a newtype or unit-like struct, define a name
510                 // in the value namespace as well
511                 if let Some(cid) = ctor_id {
512                     name_bindings.define_value(DefStruct(self.ast_map.local_def_id(cid)),
513                                                sp,
514                                                modifiers);
515                 }
516
517                 // Record the def ID and fields of this struct.
518                 let named_fields = struct_def.fields.iter().filter_map(|f| {
519                     match f.node.kind {
520                         NamedField(name, _) => Some(name),
521                         UnnamedField(_) => None
522                     }
523                 }).collect();
524                 let item_def_id = self.ast_map.local_def_id(item.id);
525                 self.structs.insert(item_def_id, named_fields);
526
527                 parent.clone()
528             }
529
530             ItemDefaultImpl(_, _) |
531             ItemImpl(..) => parent.clone(),
532
533             ItemTrait(_, _, _, ref items) => {
534                 let name_bindings =
535                     self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
536
537                 // Add all the items within to a new module.
538                 let parent_link = self.get_parent_link(parent, name);
539                 name_bindings.define_module(parent_link,
540                                             Some(self.ast_map.local_def_id(item.id)),
541                                             TraitModuleKind,
542                                             false,
543                                             is_public,
544                                             sp);
545                 let module_parent = name_bindings.get_module();
546
547                 let def_id = self.ast_map.local_def_id(item.id);
548
549                 // Add the names of all the items to the trait info.
550                 for trait_item in items {
551                     let name_bindings = self.add_child(trait_item.name,
552                                         &module_parent,
553                                         ForbidDuplicateTypesAndValues,
554                                         trait_item.span);
555
556                     match trait_item.node {
557                         hir::ConstTraitItem(..) => {
558                             let def = DefAssociatedConst(self.ast_map.local_def_id(trait_item.id));
559                             // NB: not DefModifiers::IMPORTABLE
560                             name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
561                         }
562                         hir::MethodTraitItem(..) => {
563                             let def = DefMethod(self.ast_map.local_def_id(trait_item.id));
564                             // NB: not DefModifiers::IMPORTABLE
565                             name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
566                         }
567                         hir::TypeTraitItem(..) => {
568                             let def = DefAssociatedTy(self.ast_map.local_def_id(item.id),
569                                                       self.ast_map.local_def_id(trait_item.id));
570                             // NB: not DefModifiers::IMPORTABLE
571                             name_bindings.define_type(def, trait_item.span, DefModifiers::PUBLIC);
572                         }
573                     }
574
575                     let trait_item_def_id = self.ast_map.local_def_id(trait_item.id);
576                     self.trait_item_map.insert((trait_item.name, def_id), trait_item_def_id);
577                 }
578
579                 name_bindings.define_type(DefTrait(def_id), sp, modifiers);
580                 parent.clone()
581             }
582         }
583     }
584
585     // Constructs the reduced graph for one variant. Variants exist in the
586     // type and value namespaces.
587     fn build_reduced_graph_for_variant(&mut self,
588                                        variant: &Variant,
589                                        item_id: DefId,
590                                        parent: &Rc<Module>) {
591         let name = variant.node.name;
592         let is_exported = match variant.node.kind {
593             TupleVariantKind(_) => false,
594             StructVariantKind(_) => {
595                 // Not adding fields for variants as they are not accessed with a self receiver
596                 let variant_def_id = self.ast_map.local_def_id(variant.node.id);
597                 self.structs.insert(variant_def_id, Vec::new());
598                 true
599             }
600         };
601
602         let child = self.add_child(name, parent,
603                                    ForbidDuplicateTypesAndValues,
604                                    variant.span);
605         // variants are always treated as importable to allow them to be glob
606         // used
607         child.define_value(DefVariant(item_id,
608                                       self.ast_map.local_def_id(variant.node.id), is_exported),
609                            variant.span, DefModifiers::PUBLIC | DefModifiers::IMPORTABLE);
610         child.define_type(DefVariant(item_id,
611                                      self.ast_map.local_def_id(variant.node.id), is_exported),
612                           variant.span, DefModifiers::PUBLIC | DefModifiers::IMPORTABLE);
613     }
614
615     /// Constructs the reduced graph for one foreign item.
616     fn build_reduced_graph_for_foreign_item(&mut self,
617                                             foreign_item: &ForeignItem,
618                                             parent: &Rc<Module>) {
619         let name = foreign_item.name;
620         let is_public = foreign_item.vis == hir::Public;
621         let modifiers = if is_public {
622             DefModifiers::PUBLIC
623         } else {
624             DefModifiers::empty()
625         } | DefModifiers::IMPORTABLE;
626         let name_bindings =
627             self.add_child(name, parent, ForbidDuplicateValues,
628                            foreign_item.span);
629
630         let def = match foreign_item.node {
631             ForeignItemFn(..) => {
632                 DefFn(self.ast_map.local_def_id(foreign_item.id), false)
633             }
634             ForeignItemStatic(_, m) => {
635                 DefStatic(self.ast_map.local_def_id(foreign_item.id), m)
636             }
637         };
638         name_bindings.define_value(def, foreign_item.span, modifiers);
639     }
640
641     fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc<Module>) -> Rc<Module> {
642         if self.block_needs_anonymous_module(block) {
643             let block_id = block.id;
644
645             debug!("(building reduced graph for block) creating a new \
646                     anonymous module for block {}",
647                    block_id);
648
649             let new_module = Rc::new(Module::new(
650                 BlockParentLink(Rc::downgrade(parent), block_id),
651                 None,
652                 AnonymousModuleKind,
653                 false,
654                 false));
655             parent.anonymous_children.borrow_mut().insert(block_id, new_module.clone());
656             new_module
657         } else {
658             parent.clone()
659         }
660     }
661
662     fn handle_external_def(&mut self,
663                            def: Def,
664                            vis: Visibility,
665                            child_name_bindings: &NameBindings,
666                            final_ident: &str,
667                            name: Name,
668                            new_parent: &Rc<Module>) {
669         debug!("(building reduced graph for \
670                 external crate) building external def {}, priv {:?}",
671                final_ident, vis);
672         let is_public = vis == hir::Public;
673         let modifiers = if is_public {
674             DefModifiers::PUBLIC
675         } else {
676             DefModifiers::empty()
677         } | DefModifiers::IMPORTABLE;
678         let is_exported = is_public && match new_parent.def_id.get() {
679             None => true,
680             Some(did) => self.external_exports.contains(&did)
681         };
682         if is_exported {
683             self.external_exports.insert(def.def_id());
684         }
685
686         let kind = match def {
687             DefTy(_, true) => EnumModuleKind,
688             DefTy(_, false) | DefStruct(..) => TypeModuleKind,
689             _ => NormalModuleKind
690         };
691
692         match def {
693           DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) |
694           DefTy(def_id, _) => {
695             let type_def = child_name_bindings.type_def.borrow().clone();
696             match type_def {
697               Some(TypeNsDef { module_def: Some(module_def), .. }) => {
698                 debug!("(building reduced graph for external crate) \
699                         already created module");
700                 module_def.def_id.set(Some(def_id));
701               }
702               Some(_) | None => {
703                 debug!("(building reduced graph for \
704                         external crate) building module \
705                         {} {}", final_ident, is_public);
706                 let parent_link = self.get_parent_link(new_parent, name);
707
708                 child_name_bindings.define_module(parent_link,
709                                                   Some(def_id),
710                                                   kind,
711                                                   true,
712                                                   is_public,
713                                                   DUMMY_SP);
714               }
715             }
716           }
717           _ => {}
718         }
719
720         match def {
721           DefMod(_) | DefForeignMod(_) => {}
722           DefVariant(_, variant_id, is_struct) => {
723               debug!("(building reduced graph for external crate) building \
724                       variant {}",
725                       final_ident);
726               // variants are always treated as importable to allow them to be
727               // glob used
728               let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE;
729               if is_struct {
730                   child_name_bindings.define_type(def, DUMMY_SP, modifiers);
731                   // Not adding fields for variants as they are not accessed with a self receiver
732                   self.structs.insert(variant_id, Vec::new());
733               } else {
734                   child_name_bindings.define_value(def, DUMMY_SP, modifiers);
735               }
736           }
737           DefFn(ctor_id, true) => {
738             child_name_bindings.define_value(
739                 csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
740                     .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
741           }
742           DefFn(..) | DefStatic(..) | DefConst(..) | DefAssociatedConst(..) |
743           DefMethod(..) => {
744             debug!("(building reduced graph for external \
745                     crate) building value (fn/static) {}", final_ident);
746             // impl methods have already been defined with the correct importability modifier
747             let mut modifiers = match *child_name_bindings.value_def.borrow() {
748                 Some(ref def) => (modifiers & !DefModifiers::IMPORTABLE) |
749                              (def.modifiers &  DefModifiers::IMPORTABLE),
750                 None => modifiers
751             };
752             if new_parent.kind.get() != NormalModuleKind {
753                 modifiers = modifiers & !DefModifiers::IMPORTABLE;
754             }
755             child_name_bindings.define_value(def, DUMMY_SP, modifiers);
756           }
757           DefTrait(def_id) => {
758               debug!("(building reduced graph for external \
759                       crate) building type {}", final_ident);
760
761               // If this is a trait, add all the trait item names to the trait
762               // info.
763
764               let trait_item_def_ids =
765                 csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
766               for trait_item_def in &trait_item_def_ids {
767                   let trait_item_name = csearch::get_trait_name(&self.session.cstore,
768                                                                 trait_item_def.def_id());
769
770                   debug!("(building reduced graph for external crate) ... \
771                           adding trait item '{}'",
772                          trait_item_name);
773
774                   self.trait_item_map.insert((trait_item_name, def_id),
775                                              trait_item_def.def_id());
776
777                   if is_exported {
778                       self.external_exports.insert(trait_item_def.def_id());
779                   }
780               }
781
782               child_name_bindings.define_type(def, DUMMY_SP, modifiers);
783
784               // Define a module if necessary.
785               let parent_link = self.get_parent_link(new_parent, name);
786               child_name_bindings.set_module_kind(parent_link,
787                                                   Some(def_id),
788                                                   TraitModuleKind,
789                                                   true,
790                                                   is_public,
791                                                   DUMMY_SP)
792           }
793           DefTy(..) | DefAssociatedTy(..) => {
794               debug!("(building reduced graph for external \
795                       crate) building type {}", final_ident);
796
797               let modifiers = match new_parent.kind.get() {
798                   NormalModuleKind => modifiers,
799                   _ => modifiers & !DefModifiers::IMPORTABLE
800               };
801
802               child_name_bindings.define_type(def, DUMMY_SP, modifiers);
803           }
804           DefStruct(def_id) => {
805             debug!("(building reduced graph for external \
806                     crate) building type and value for {}",
807                    final_ident);
808             child_name_bindings.define_type(def, DUMMY_SP, modifiers);
809             let fields = csearch::get_struct_field_names(&self.session.cstore, def_id);
810
811             if fields.is_empty() {
812                 child_name_bindings.define_value(def, DUMMY_SP, modifiers);
813             }
814
815             // Record the def ID and fields of this struct.
816             self.structs.insert(def_id, fields);
817           }
818           DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
819           DefUse(..) | DefUpvar(..) |
820           DefLabel(..) | DefSelfTy(..) => {
821             panic!("didn't expect `{:?}`", def);
822           }
823         }
824     }
825
826     /// Builds the reduced graph for a single item in an external crate.
827     fn build_reduced_graph_for_external_crate_def(&mut self,
828                                                   root: &Rc<Module>,
829                                                   def_like: DefLike,
830                                                   name: Name,
831                                                   def_visibility: Visibility) {
832         match def_like {
833             DlDef(def) => {
834                 // Add the new child item, if necessary.
835                 match def {
836                     DefForeignMod(def_id) => {
837                         // Foreign modules have no names. Recur and populate
838                         // eagerly.
839                         csearch::each_child_of_item(&self.session.cstore,
840                                                     def_id,
841                                                     |def_like,
842                                                      child_name,
843                                                      vis| {
844                             self.build_reduced_graph_for_external_crate_def(
845                                 root,
846                                 def_like,
847                                 child_name,
848                                 vis)
849                         });
850                     }
851                     _ => {
852                         let child_name_bindings =
853                             self.add_child(name,
854                                            root,
855                                            OverwriteDuplicates,
856                                            DUMMY_SP);
857
858                         self.handle_external_def(def,
859                                                  def_visibility,
860                                                  &*child_name_bindings,
861                                                  &name.as_str(),
862                                                  name,
863                                                  root);
864                     }
865                 }
866             }
867             DlImpl(_) => {
868                 debug!("(building reduced graph for external crate) \
869                         ignoring impl");
870             }
871             DlField => {
872                 debug!("(building reduced graph for external crate) \
873                         ignoring field");
874             }
875         }
876     }
877
878     /// Builds the reduced graph rooted at the given external module.
879     fn populate_external_module(&mut self, module: &Rc<Module>) {
880         debug!("(populating external module) attempting to populate {}",
881                module_to_string(&**module));
882
883         let def_id = match module.def_id.get() {
884             None => {
885                 debug!("(populating external module) ... no def ID!");
886                 return
887             }
888             Some(def_id) => def_id,
889         };
890
891         csearch::each_child_of_item(&self.session.cstore,
892                                     def_id,
893                                     |def_like, child_name, visibility| {
894             debug!("(populating external module) ... found ident: {}",
895                    child_name);
896             self.build_reduced_graph_for_external_crate_def(module,
897                                                             def_like,
898                                                             child_name,
899                                                             visibility)
900         });
901         module.populated.set(true)
902     }
903
904     /// Ensures that the reduced graph rooted at the given external module
905     /// is built, building it if it is not.
906     fn populate_module_if_necessary(&mut self, module: &Rc<Module>) {
907         if !module.populated.get() {
908             self.populate_external_module(module)
909         }
910         assert!(module.populated.get())
911     }
912
913     /// Builds the reduced graph rooted at the 'use' directive for an external
914     /// crate.
915     fn build_reduced_graph_for_external_crate(&mut self, root: &Rc<Module>) {
916         csearch::each_top_level_item_of_crate(&self.session.cstore,
917                                               root.def_id
918                                                   .get()
919                                                   .unwrap()
920                                                   .krate,
921                                               |def_like, name, visibility| {
922             self.build_reduced_graph_for_external_crate_def(root, def_like, name, visibility)
923         });
924     }
925
926     /// Creates and adds an import directive to the given module.
927     fn build_import_directive(&mut self,
928                               module_: &Module,
929                               module_path: Vec<Name>,
930                               subclass: ImportDirectiveSubclass,
931                               span: Span,
932                               id: NodeId,
933                               is_public: bool,
934                               shadowable: Shadowable) {
935         module_.imports.borrow_mut().push(ImportDirective::new(module_path,
936                                                                subclass,
937                                                                span,
938                                                                id,
939                                                                is_public,
940                                                                shadowable));
941         self.unresolved_imports += 1;
942
943         if is_public {
944             module_.inc_pub_count();
945         }
946
947         // Bump the reference count on the name. Or, if this is a glob, set
948         // the appropriate flag.
949
950         match subclass {
951             SingleImport(target, _) => {
952                 debug!("(building import directive) building import directive: {}::{}",
953                        names_to_string(&module_.imports.borrow().last().unwrap().module_path),
954                        target);
955
956                 let mut import_resolutions = module_.import_resolutions.borrow_mut();
957                 match import_resolutions.get_mut(&target) {
958                     Some(resolution) => {
959                         debug!("(building import directive) bumping reference");
960                         resolution.outstanding_references += 1;
961
962                         // the source of this name is different now
963                         resolution.type_id = id;
964                         resolution.value_id = id;
965                         resolution.is_public = is_public;
966                         return;
967                     }
968                     None => {}
969                 }
970                 debug!("(building import directive) creating new");
971                 let mut resolution = ImportResolution::new(id, is_public);
972                 resolution.outstanding_references = 1;
973                 import_resolutions.insert(target, resolution);
974             }
975             GlobImport => {
976                 // Set the glob flag. This tells us that we don't know the
977                 // module's exports ahead of time.
978
979                 module_.inc_glob_count();
980                 if is_public {
981                     module_.inc_pub_glob_count();
982                 }
983             }
984         }
985     }
986 }
987
988 struct BuildReducedGraphVisitor<'a, 'b:'a, 'tcx:'b> {
989     builder: GraphBuilder<'a, 'b, 'tcx>,
990     parent: Rc<Module>
991 }
992
993 impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
994     fn visit_item(&mut self, item: &Item) {
995         let p = self.builder.build_reduced_graph_for_item(item, &self.parent);
996         let old_parent = replace(&mut self.parent, p);
997         visit::walk_item(self, item);
998         self.parent = old_parent;
999     }
1000
1001     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
1002         self.builder.build_reduced_graph_for_foreign_item(foreign_item, &self.parent);
1003     }
1004
1005     fn visit_block(&mut self, block: &Block) {
1006         let np = self.builder.build_reduced_graph_for_block(block, &self.parent);
1007         let old_parent = replace(&mut self.parent, np);
1008         visit::walk_block(self, block);
1009         self.parent = old_parent;
1010     }
1011 }
1012
1013 pub fn build_reduced_graph(resolver: &mut Resolver, krate: &hir::Crate) {
1014     GraphBuilder {
1015         resolver: resolver
1016     }.build_reduced_graph(krate);
1017 }
1018
1019 pub fn populate_module_if_necessary(resolver: &mut Resolver, module: &Rc<Module>) {
1020     GraphBuilder {
1021         resolver: resolver
1022     }.populate_module_if_necessary(module);
1023 }