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