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