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