]> git.lizzy.rs Git - rust.git/blob - src/librustc_resolve/build_reduced_graph.rs
Merge pull request #20510 from tshepang/patch-6
[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, PUBLIC, IMPORTABLE};
17 use ImportDirective;
18 use ImportDirectiveSubclass::{self, SingleImport, GlobImport};
19 use ImportResolution;
20 use Module;
21 use ModuleKind::*;
22 use Namespace::{TypeNS, ValueNS};
23 use NameBindings;
24 use ParentLink::{self, ModuleParentLink, BlockParentLink};
25 use Resolver;
26 use RibKind::*;
27 use Shadowable;
28 use TypeNsDef;
29 use TypeParameters::HasTypeParameters;
30
31 use self::DuplicateCheckingMode::*;
32 use self::NamespaceError::*;
33
34 use rustc::metadata::csearch;
35 use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
36 use rustc::middle::def::*;
37 use rustc::middle::subst::FnSpace;
38
39 use syntax::ast::{Block, Crate};
40 use syntax::ast::{DeclItem, DefId};
41 use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic};
42 use syntax::ast::{Item, ItemConst, ItemEnum, ItemFn};
43 use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
44 use syntax::ast::{ItemStruct, ItemTrait, ItemTy};
45 use syntax::ast::{MethodImplItem, Name, NamedField, NodeId};
46 use syntax::ast::{PathListIdent, PathListMod};
47 use syntax::ast::{Public, SelfStatic};
48 use syntax::ast::StmtDecl;
49 use syntax::ast::StructVariantKind;
50 use syntax::ast::TupleVariantKind;
51 use syntax::ast::TyObjectSum;
52 use syntax::ast::{TypeImplItem, UnnamedField};
53 use syntax::ast::{Variant, ViewItem, ViewItemExternCrate};
54 use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple};
55 use syntax::ast::{Visibility};
56 use syntax::ast::TyPath;
57 use syntax::ast;
58 use syntax::ast_util::{self, PostExpansionMethod, local_def};
59 use syntax::attr::AttrMetaMethods;
60 use syntax::parse::token::{self, special_idents};
61 use syntax::codemap::{Span, DUMMY_SP};
62 use syntax::visit::{self, Visitor};
63
64 use std::mem::replace;
65 use std::ops::{Deref, DerefMut};
66 use std::rc::Rc;
67
68 // Specifies how duplicates should be handled when adding a child item if
69 // another item exists with the same name in some namespace.
70 #[derive(Copy, PartialEq)]
71 enum DuplicateCheckingMode {
72     ForbidDuplicateModules,
73     ForbidDuplicateTypesAndModules,
74     ForbidDuplicateValues,
75     ForbidDuplicateTypesAndValues,
76     OverwriteDuplicates
77 }
78
79 #[derive(Copy, PartialEq)]
80 enum NamespaceError {
81     NoError,
82     ModuleError,
83     TypeError,
84     ValueError
85 }
86
87 fn namespace_error_to_string(ns: NamespaceError) -> &'static str {
88     match ns {
89         NoError                 => "",
90         ModuleError | TypeError => "type or module",
91         ValueError              => "value",
92     }
93 }
94
95 struct GraphBuilder<'a, 'b:'a, 'tcx:'b> {
96     resolver: &'a mut Resolver<'b, 'tcx>
97 }
98
99 impl<'a, 'b:'a, 'tcx:'b> Deref for GraphBuilder<'a, 'b, 'tcx> {
100     type Target = Resolver<'b, 'tcx>;
101
102     fn deref(&self) -> &Resolver<'b, 'tcx> {
103         &*self.resolver
104     }
105 }
106
107 impl<'a, 'b:'a, 'tcx:'b> DerefMut for GraphBuilder<'a, 'b, 'tcx> {
108     fn deref_mut(&mut self) -> &mut Resolver<'b, 'tcx> {
109         &mut *self.resolver
110     }
111 }
112
113 impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
114     /// Constructs the reduced graph for the entire crate.
115     fn build_reduced_graph(self, krate: &ast::Crate) {
116         let parent = self.graph_root.get_module();
117         let mut visitor = BuildReducedGraphVisitor {
118             builder: self,
119             parent: parent
120         };
121         visit::walk_crate(&mut visitor, krate);
122     }
123
124     /// Adds a new child item to the module definition of the parent node and
125     /// returns its corresponding name bindings as well as the current parent.
126     /// Or, if we're inside a block, creates (or reuses) an anonymous module
127     /// corresponding to the innermost block ID and returns the name bindings
128     /// as well as the newly-created parent.
129     ///
130     /// # Panics
131     ///
132     /// Panics if this node does not have a module definition and we are not inside
133     /// a block.
134     fn add_child(&self,
135                  name: Name,
136                  parent: &Rc<Module>,
137                  duplicate_checking_mode: DuplicateCheckingMode,
138                  // For printing errors
139                  sp: Span)
140                  -> Rc<NameBindings> {
141         // If this is the immediate descendant of a module, then we add the
142         // child name directly. Otherwise, we create or reuse an anonymous
143         // module and add the child to that.
144
145         self.check_for_conflicts_between_external_crates_and_items(&**parent,
146                                                                    name,
147                                                                    sp);
148
149         // Add or reuse the child.
150         let child = parent.children.borrow().get(&name).cloned();
151         match child {
152             None => {
153                 let child = Rc::new(NameBindings::new());
154                 parent.children.borrow_mut().insert(name, child.clone());
155                 child
156             }
157             Some(child) => {
158                 // Enforce the duplicate checking mode:
159                 //
160                 // * If we're requesting duplicate module checking, check that
161                 //   there isn't a module in the module with the same name.
162                 //
163                 // * If we're requesting duplicate type checking, check that
164                 //   there isn't a type in the module with the same name.
165                 //
166                 // * If we're requesting duplicate value checking, check that
167                 //   there isn't a value in the module with the same name.
168                 //
169                 // * If we're requesting duplicate type checking and duplicate
170                 //   value checking, check that there isn't a duplicate type
171                 //   and a duplicate value with the same name.
172                 //
173                 // * If no duplicate checking was requested at all, do
174                 //   nothing.
175
176                 let mut duplicate_type = NoError;
177                 let ns = match duplicate_checking_mode {
178                     ForbidDuplicateModules => {
179                         if child.get_module_if_available().is_some() {
180                             duplicate_type = ModuleError;
181                         }
182                         Some(TypeNS)
183                     }
184                     ForbidDuplicateTypesAndModules => {
185                         match child.def_for_namespace(TypeNS) {
186                             None => {}
187                             Some(_) if child.get_module_if_available()
188                                             .map(|m| m.kind.get()) ==
189                                        Some(ImplModuleKind) => {}
190                             Some(_) => duplicate_type = TypeError
191                         }
192                         Some(TypeNS)
193                     }
194                     ForbidDuplicateValues => {
195                         if child.defined_in_namespace(ValueNS) {
196                             duplicate_type = ValueError;
197                         }
198                         Some(ValueNS)
199                     }
200                     ForbidDuplicateTypesAndValues => {
201                         let mut n = None;
202                         match child.def_for_namespace(TypeNS) {
203                             Some(DefMod(_)) | None => {}
204                             Some(_) => {
205                                 n = Some(TypeNS);
206                                 duplicate_type = TypeError;
207                             }
208                         };
209                         if child.defined_in_namespace(ValueNS) {
210                             duplicate_type = ValueError;
211                             n = Some(ValueNS);
212                         }
213                         n
214                     }
215                     OverwriteDuplicates => None
216                 };
217                 if duplicate_type != NoError {
218                     // Return an error here by looking up the namespace that
219                     // had the duplicate.
220                     let ns = ns.unwrap();
221                     self.resolve_error(sp,
222                         format!("duplicate definition of {} `{}`",
223                              namespace_error_to_string(duplicate_type),
224                              token::get_name(name))[]);
225                     {
226                         let r = child.span_for_namespace(ns);
227                         for sp in r.iter() {
228                             self.session.span_note(*sp,
229                                  format!("first definition of {} `{}` here",
230                                       namespace_error_to_string(duplicate_type),
231                                       token::get_name(name))[]);
232                         }
233                     }
234                 }
235                 child
236             }
237         }
238     }
239
240     fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
241         // If the block has view items, we need an anonymous module.
242         if block.view_items.len() > 0 {
243             return true;
244         }
245
246         // Check each statement.
247         for statement in block.stmts.iter() {
248             match statement.node {
249                 StmtDecl(ref declaration, _) => {
250                     match declaration.node {
251                         DeclItem(_) => {
252                             return true;
253                         }
254                         _ => {
255                             // Keep searching.
256                         }
257                     }
258                 }
259                 _ => {
260                     // Keep searching.
261                 }
262             }
263         }
264
265         // If we found neither view items nor items, we don't need to create
266         // an anonymous module.
267
268         return false;
269     }
270
271     fn get_parent_link(&mut self, parent: &Rc<Module>, name: Name) -> ParentLink {
272         ModuleParentLink(parent.downgrade(), name)
273     }
274
275     /// Constructs the reduced graph for one item.
276     fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) -> Rc<Module> {
277         let name = item.ident.name;
278         let sp = item.span;
279         let is_public = item.vis == ast::Public;
280         let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
281
282         match item.node {
283             ItemMod(..) => {
284                 let name_bindings = self.add_child(name, parent, ForbidDuplicateModules, sp);
285
286                 let parent_link = self.get_parent_link(parent, name);
287                 let def_id = DefId { krate: 0, node: item.id };
288                 name_bindings.define_module(parent_link,
289                                             Some(def_id),
290                                             NormalModuleKind,
291                                             false,
292                                             item.vis == ast::Public,
293                                             sp);
294
295                 name_bindings.get_module()
296             }
297
298             ItemForeignMod(..) => parent.clone(),
299
300             // These items live in the value namespace.
301             ItemStatic(_, m, _) => {
302                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
303                 let mutbl = m == ast::MutMutable;
304
305                 name_bindings.define_value(DefStatic(local_def(item.id), mutbl), sp, modifiers);
306                 parent.clone()
307             }
308             ItemConst(_, _) => {
309                 self.add_child(name, parent, ForbidDuplicateValues, sp)
310                     .define_value(DefConst(local_def(item.id)), sp, modifiers);
311                 parent.clone()
312             }
313             ItemFn(_, _, _, _, _) => {
314                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
315
316                 let def = DefFn(local_def(item.id), false);
317                 name_bindings.define_value(def, sp, modifiers);
318                 parent.clone()
319             }
320
321             // These items live in the type namespace.
322             ItemTy(..) => {
323                 let name_bindings =
324                     self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
325
326                 name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers);
327                 parent.clone()
328             }
329
330             ItemEnum(ref enum_definition, _) => {
331                 let name_bindings =
332                     self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
333
334                 name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers);
335
336                 let parent_link = self.get_parent_link(parent, name);
337                 // We want to make sure the module type is EnumModuleKind
338                 // even if there's already an ImplModuleKind module defined,
339                 // since that's how we prevent duplicate enum definitions
340                 name_bindings.set_module_kind(parent_link,
341                                               Some(local_def(item.id)),
342                                               EnumModuleKind,
343                                               false,
344                                               is_public,
345                                               sp);
346
347                 let module = name_bindings.get_module();
348
349                 for variant in (*enum_definition).variants.iter() {
350                     self.build_reduced_graph_for_variant(
351                         &**variant,
352                         local_def(item.id),
353                         &module);
354                 }
355                 parent.clone()
356             }
357
358             // These items live in both the type and value namespaces.
359             ItemStruct(ref struct_def, _) => {
360                 // Adding to both Type and Value namespaces or just Type?
361                 let (forbid, ctor_id) = match struct_def.ctor_id {
362                     Some(ctor_id)   => (ForbidDuplicateTypesAndValues, Some(ctor_id)),
363                     None            => (ForbidDuplicateTypesAndModules, None)
364                 };
365
366                 let name_bindings = self.add_child(name, parent, forbid, sp);
367
368                 // Define a name in the type namespace.
369                 name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers);
370
371                 // If this is a newtype or unit-like struct, define a name
372                 // in the value namespace as well
373                 if let Some(cid) = ctor_id {
374                     name_bindings.define_value(DefStruct(local_def(cid)), sp, modifiers);
375                 }
376
377                 // Record the def ID and fields of this struct.
378                 let named_fields = struct_def.fields.iter().filter_map(|f| {
379                     match f.node.kind {
380                         NamedField(ident, _) => Some(ident.name),
381                         UnnamedField(_) => None
382                     }
383                 }).collect();
384                 self.structs.insert(local_def(item.id), named_fields);
385
386                 parent.clone()
387             }
388
389             ItemImpl(_, _, None, ref ty, ref impl_items) => {
390                 // If this implements an anonymous trait, then add all the
391                 // methods within to a new module, if the type was defined
392                 // within this module.
393
394                 let mod_name = match ty.node {
395                     TyPath(ref path, _) if path.segments.len() == 1 => {
396                         // FIXME(18446) we should distinguish between the name of
397                         // a trait and the name of an impl of that trait.
398                         Some(path.segments.last().unwrap().identifier.name)
399                     }
400                     TyObjectSum(ref lhs_ty, _) => {
401                         match lhs_ty.node {
402                             TyPath(ref path, _) if path.segments.len() == 1 => {
403                                 Some(path.segments.last().unwrap().identifier.name)
404                             }
405                             _ => {
406                                 None
407                             }
408                         }
409                     }
410                     _ => {
411                         None
412                     }
413                 };
414
415                 match mod_name {
416                     None => {
417                         self.resolve_error(ty.span,
418                                            "inherent implementations may \
419                                             only be implemented in the same \
420                                             module as the type they are \
421                                             implemented for")
422                     }
423                     Some(mod_name) => {
424                         // Create the module and add all methods.
425                         let parent_opt = parent.children.borrow().get(&mod_name).cloned();
426                         let new_parent = match parent_opt {
427                             // It already exists
428                             Some(ref child) if child.get_module_if_available()
429                                 .is_some() &&
430                                 (child.get_module().kind.get() == ImplModuleKind ||
431                                  child.get_module().kind.get() == TraitModuleKind) => {
432                                     child.get_module()
433                                 }
434                             Some(ref child) if child.get_module_if_available()
435                                 .is_some() &&
436                                 child.get_module().kind.get() ==
437                                 EnumModuleKind => child.get_module(),
438                             // Create the module
439                             _ => {
440                                 let name_bindings =
441                                     self.add_child(mod_name, parent, ForbidDuplicateModules, sp);
442
443                                 let parent_link = self.get_parent_link(parent, name);
444                                 let def_id = local_def(item.id);
445                                 let ns = TypeNS;
446                                 let is_public =
447                                     !name_bindings.defined_in_namespace(ns) ||
448                                     name_bindings.defined_in_public_namespace(ns);
449
450                                 name_bindings.define_module(parent_link,
451                                                             Some(def_id),
452                                                             ImplModuleKind,
453                                                             false,
454                                                             is_public,
455                                                             sp);
456
457                                 name_bindings.get_module()
458                             }
459                         };
460
461                         // For each implementation item...
462                         for impl_item in impl_items.iter() {
463                             match *impl_item {
464                                 MethodImplItem(ref method) => {
465                                     // Add the method to the module.
466                                     let name = method.pe_ident().name;
467                                     let method_name_bindings =
468                                         self.add_child(name,
469                                                        &new_parent,
470                                                        ForbidDuplicateValues,
471                                                        method.span);
472                                     let def = match method.pe_explicit_self()
473                                         .node {
474                                             SelfStatic => {
475                                                 // Static methods become
476                                                 // `DefStaticMethod`s.
477                                                 DefStaticMethod(local_def(method.id),
478                                                                 FromImpl(local_def(item.id)))
479                                             }
480                                             _ => {
481                                                 // Non-static methods become
482                                                 // `DefMethod`s.
483                                                 DefMethod(local_def(method.id),
484                                                           None,
485                                                           FromImpl(local_def(item.id)))
486                                             }
487                                         };
488
489                                     // NB: not IMPORTABLE
490                                     let modifiers = if method.pe_vis() == ast::Public {
491                                         PUBLIC
492                                     } else {
493                                         DefModifiers::empty()
494                                     };
495                                     method_name_bindings.define_value(
496                                         def,
497                                         method.span,
498                                         modifiers);
499                                 }
500                                 TypeImplItem(ref typedef) => {
501                                     // Add the typedef to the module.
502                                     let name = typedef.ident.name;
503                                     let typedef_name_bindings =
504                                         self.add_child(
505                                             name,
506                                             &new_parent,
507                                             ForbidDuplicateTypesAndModules,
508                                             typedef.span);
509                                     let def = DefAssociatedTy(local_def(
510                                         typedef.id));
511                                     // NB: not IMPORTABLE
512                                     let modifiers = if typedef.vis == ast::Public {
513                                         PUBLIC
514                                     } else {
515                                         DefModifiers::empty()
516                                     };
517                                     typedef_name_bindings.define_type(
518                                         def,
519                                         typedef.span,
520                                         modifiers);
521                                 }
522                             }
523                         }
524                     }
525                 }
526
527                 parent.clone()
528             }
529
530             ItemImpl(_, _, Some(_), _, _) => parent.clone(),
531
532             ItemTrait(_, _, _, ref items) => {
533                 let name_bindings =
534                     self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
535
536                 // Add all the items within to a new module.
537                 let parent_link = self.get_parent_link(parent, name);
538                 name_bindings.define_module(parent_link,
539                                             Some(local_def(item.id)),
540                                             TraitModuleKind,
541                                             false,
542                                             item.vis == ast::Public,
543                                             sp);
544                 let module_parent = name_bindings.get_module();
545
546                 let def_id = local_def(item.id);
547
548                 // Add the names of all the items to the trait info.
549                 for trait_item in items.iter() {
550                     let (name, kind) = match *trait_item {
551                         ast::RequiredMethod(_) |
552                         ast::ProvidedMethod(_) => {
553                             let ty_m = ast_util::trait_item_to_ty_method(trait_item);
554
555                             let name = ty_m.ident.name;
556
557                             // Add it as a name in the trait module.
558                             let (def, static_flag) = match ty_m.explicit_self
559                                                                .node {
560                                 SelfStatic => {
561                                     // Static methods become `DefStaticMethod`s.
562                                     (DefStaticMethod(
563                                             local_def(ty_m.id),
564                                             FromTrait(local_def(item.id))),
565                                      StaticMethodTraitItemKind)
566                                 }
567                                 _ => {
568                                     // Non-static methods become `DefMethod`s.
569                                     (DefMethod(local_def(ty_m.id),
570                                                Some(local_def(item.id)),
571                                                FromTrait(local_def(item.id))),
572                                      NonstaticMethodTraitItemKind)
573                                 }
574                             };
575
576                             let method_name_bindings =
577                                 self.add_child(name,
578                                                &module_parent,
579                                                ForbidDuplicateTypesAndValues,
580                                                ty_m.span);
581                             // NB: not IMPORTABLE
582                             method_name_bindings.define_value(def,
583                                                               ty_m.span,
584                                                               PUBLIC);
585
586                             (name, static_flag)
587                         }
588                         ast::TypeTraitItem(ref associated_type) => {
589                             let def = DefAssociatedTy(local_def(
590                                     associated_type.ty_param.id));
591
592                             let name_bindings =
593                                 self.add_child(associated_type.ty_param.ident.name,
594                                                &module_parent,
595                                                ForbidDuplicateTypesAndValues,
596                                                associated_type.ty_param.span);
597                             // NB: not IMPORTABLE
598                             name_bindings.define_type(def,
599                                                       associated_type.ty_param.span,
600                                                       PUBLIC);
601
602                             (associated_type.ty_param.ident.name, TypeTraitItemKind)
603                         }
604                     };
605
606                     self.trait_item_map.insert((name, def_id), kind);
607                 }
608
609                 name_bindings.define_type(DefTrait(def_id), sp, modifiers);
610                 parent.clone()
611             }
612             ItemMac(..) => parent.clone()
613         }
614     }
615
616     // Constructs the reduced graph for one variant. Variants exist in the
617     // type and value namespaces.
618     fn build_reduced_graph_for_variant(&mut self,
619                                        variant: &Variant,
620                                        item_id: DefId,
621                                        parent: &Rc<Module>) {
622         let name = variant.node.name.name;
623         let is_exported = match variant.node.kind {
624             TupleVariantKind(_) => false,
625             StructVariantKind(_) => {
626                 // Not adding fields for variants as they are not accessed with a self receiver
627                 self.structs.insert(local_def(variant.node.id), Vec::new());
628                 true
629             }
630         };
631
632         let child = self.add_child(name, parent,
633                                    ForbidDuplicateTypesAndValues,
634                                    variant.span);
635         // variants are always treated as importable to allow them to be glob
636         // used
637         child.define_value(DefVariant(item_id,
638                                       local_def(variant.node.id), is_exported),
639                            variant.span, PUBLIC | IMPORTABLE);
640         child.define_type(DefVariant(item_id,
641                                      local_def(variant.node.id), is_exported),
642                           variant.span, PUBLIC | IMPORTABLE);
643     }
644
645     /// Constructs the reduced graph for one 'view item'. View items consist
646     /// of imports and use directives.
647     fn build_reduced_graph_for_view_item(&mut self, view_item: &ViewItem, parent: &Rc<Module>) {
648         match view_item.node {
649             ViewItemUse(ref view_path) => {
650                 // Extract and intern the module part of the path. For
651                 // globs and lists, the path is found directly in the AST;
652                 // for simple paths we have to munge the path a little.
653                 let module_path = match view_path.node {
654                     ViewPathSimple(_, ref full_path, _) => {
655                         full_path.segments
656                             .init()
657                             .iter().map(|ident| ident.identifier.name)
658                             .collect()
659                     }
660
661                     ViewPathGlob(ref module_ident_path, _) |
662                     ViewPathList(ref module_ident_path, _, _) => {
663                         module_ident_path.segments
664                             .iter().map(|ident| ident.identifier.name).collect()
665                     }
666                 };
667
668                 // Build up the import directives.
669                 let is_public = view_item.vis == ast::Public;
670                 let shadowable =
671                     view_item.attrs
672                              .iter()
673                              .any(|attr| {
674                                  attr.name() == token::get_name(
675                                     special_idents::prelude_import.name)
676                              });
677                 let shadowable = if shadowable {
678                     Shadowable::Always
679                 } else {
680                     Shadowable::Never
681                 };
682
683                 match view_path.node {
684                     ViewPathSimple(binding, ref full_path, id) => {
685                         let source_name =
686                             full_path.segments.last().unwrap().identifier.name;
687                         if token::get_name(source_name).get() == "mod" ||
688                            token::get_name(source_name).get() == "self" {
689                             self.resolve_error(view_path.span,
690                                 "`self` imports are only allowed within a { } list");
691                         }
692
693                         let subclass = SingleImport(binding.name,
694                                                     source_name);
695                         self.build_import_directive(&**parent,
696                                                     module_path,
697                                                     subclass,
698                                                     view_path.span,
699                                                     id,
700                                                     is_public,
701                                                     shadowable);
702                     }
703                     ViewPathList(_, ref source_items, _) => {
704                         // Make sure there's at most one `mod` import in the list.
705                         let mod_spans = source_items.iter().filter_map(|item| match item.node {
706                             PathListMod { .. } => Some(item.span),
707                             _ => None
708                         }).collect::<Vec<Span>>();
709                         if mod_spans.len() > 1 {
710                             self.resolve_error(mod_spans[0],
711                                 "`self` import can only appear once in the list");
712                             for other_span in mod_spans.iter().skip(1) {
713                                 self.session.span_note(*other_span,
714                                     "another `self` import appears here");
715                             }
716                         }
717
718                         for source_item in source_items.iter() {
719                             let (module_path, name) = match source_item.node {
720                                 PathListIdent { name, .. } =>
721                                     (module_path.clone(), name.name),
722                                 PathListMod { .. } => {
723                                     let name = match module_path.last() {
724                                         Some(name) => *name,
725                                         None => {
726                                             self.resolve_error(source_item.span,
727                                                 "`self` import can only appear in an import list \
728                                                  with a non-empty prefix");
729                                             continue;
730                                         }
731                                     };
732                                     let module_path = module_path.init();
733                                     (module_path.to_vec(), name)
734                                 }
735                             };
736                             self.build_import_directive(
737                                 &**parent,
738                                 module_path,
739                                 SingleImport(name, name),
740                                 source_item.span,
741                                 source_item.node.id(),
742                                 is_public,
743                                 shadowable);
744                         }
745                     }
746                     ViewPathGlob(_, id) => {
747                         self.build_import_directive(&**parent,
748                                                     module_path,
749                                                     GlobImport,
750                                                     view_path.span,
751                                                     id,
752                                                     is_public,
753                                                     shadowable);
754                     }
755                 }
756             }
757
758             ViewItemExternCrate(name, _, node_id) => {
759                 // n.b. we don't need to look at the path option here, because cstore already did
760                 for &crate_id in self.session.cstore
761                                      .find_extern_mod_stmt_cnum(node_id).iter() {
762                     let def_id = DefId { krate: crate_id, node: 0 };
763                     self.external_exports.insert(def_id);
764                     let parent_link = ModuleParentLink(parent.downgrade(), name.name);
765                     let external_module = Rc::new(Module::new(parent_link,
766                                                               Some(def_id),
767                                                               NormalModuleKind,
768                                                               false,
769                                                               true));
770                     debug!("(build reduced graph for item) found extern `{}`",
771                             self.module_to_string(&*external_module));
772                     self.check_for_conflicts_between_external_crates(
773                         &**parent,
774                         name.name,
775                         view_item.span);
776                     parent.external_module_children.borrow_mut()
777                           .insert(name.name, external_module.clone());
778                     self.build_reduced_graph_for_external_crate(&external_module);
779                 }
780             }
781         }
782     }
783
784     /// Constructs the reduced graph for one foreign item.
785     fn build_reduced_graph_for_foreign_item<F>(&mut self,
786                                                foreign_item: &ForeignItem,
787                                                parent: &Rc<Module>,
788                                                f: F) where
789         F: FnOnce(&mut Resolver),
790     {
791         let name = foreign_item.ident.name;
792         let is_public = foreign_item.vis == ast::Public;
793         let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
794         let name_bindings =
795             self.add_child(name, parent, ForbidDuplicateValues,
796                            foreign_item.span);
797
798         match foreign_item.node {
799             ForeignItemFn(_, ref generics) => {
800                 let def = DefFn(local_def(foreign_item.id), false);
801                 name_bindings.define_value(def, foreign_item.span, modifiers);
802
803                 self.with_type_parameter_rib(
804                     HasTypeParameters(generics,
805                                       FnSpace,
806                                       foreign_item.id,
807                                       NormalRibKind),
808                     f);
809             }
810             ForeignItemStatic(_, m) => {
811                 let def = DefStatic(local_def(foreign_item.id), m);
812                 name_bindings.define_value(def, foreign_item.span, modifiers);
813
814                 f(self.resolver)
815             }
816         }
817     }
818
819     fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc<Module>) -> Rc<Module> {
820         if self.block_needs_anonymous_module(block) {
821             let block_id = block.id;
822
823             debug!("(building reduced graph for block) creating a new \
824                     anonymous module for block {}",
825                    block_id);
826
827             let new_module = Rc::new(Module::new(
828                 BlockParentLink(parent.downgrade(), block_id),
829                 None,
830                 AnonymousModuleKind,
831                 false,
832                 false));
833             parent.anonymous_children.borrow_mut().insert(block_id, new_module.clone());
834             new_module
835         } else {
836             parent.clone()
837         }
838     }
839
840     fn handle_external_def(&mut self,
841                            def: Def,
842                            vis: Visibility,
843                            child_name_bindings: &NameBindings,
844                            final_ident: &str,
845                            name: Name,
846                            new_parent: &Rc<Module>) {
847         debug!("(building reduced graph for \
848                 external crate) building external def, priv {}",
849                vis);
850         let is_public = vis == ast::Public;
851         let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
852         let is_exported = is_public && match new_parent.def_id.get() {
853             None => true,
854             Some(did) => self.external_exports.contains(&did)
855         };
856         if is_exported {
857             self.external_exports.insert(def.def_id());
858         }
859
860         let kind = match def {
861             DefTy(_, true) => EnumModuleKind,
862             DefStruct(..) | DefTy(..) => ImplModuleKind,
863             _ => NormalModuleKind
864         };
865
866         match def {
867           DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) |
868           DefTy(def_id, _) => {
869             let type_def = child_name_bindings.type_def.borrow().clone();
870             match type_def {
871               Some(TypeNsDef { module_def: Some(module_def), .. }) => {
872                 debug!("(building reduced graph for external crate) \
873                         already created module");
874                 module_def.def_id.set(Some(def_id));
875               }
876               Some(_) | None => {
877                 debug!("(building reduced graph for \
878                         external crate) building module \
879                         {}", final_ident);
880                 let parent_link = self.get_parent_link(new_parent, name);
881
882                 child_name_bindings.define_module(parent_link,
883                                                   Some(def_id),
884                                                   kind,
885                                                   true,
886                                                   is_public,
887                                                   DUMMY_SP);
888               }
889             }
890           }
891           _ => {}
892         }
893
894         match def {
895           DefMod(_) | DefForeignMod(_) => {}
896           DefVariant(_, variant_id, is_struct) => {
897               debug!("(building reduced graph for external crate) building \
898                       variant {}",
899                       final_ident);
900               // variants are always treated as importable to allow them to be
901               // glob used
902               let modifiers = PUBLIC | IMPORTABLE;
903               if is_struct {
904                   child_name_bindings.define_type(def, DUMMY_SP, modifiers);
905                   // Not adding fields for variants as they are not accessed with a self receiver
906                   self.structs.insert(variant_id, Vec::new());
907               } else {
908                   child_name_bindings.define_value(def, DUMMY_SP, modifiers);
909               }
910           }
911           DefFn(ctor_id, true) => {
912             child_name_bindings.define_value(
913                 csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
914                     .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
915           }
916           DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
917             debug!("(building reduced graph for external \
918                     crate) building value (fn/static) {}", final_ident);
919             // impl methods have already been defined with the correct importability modifier
920             let mut modifiers = match *child_name_bindings.value_def.borrow() {
921                 Some(ref def) => (modifiers & !IMPORTABLE) | (def.modifiers & IMPORTABLE),
922                 None => modifiers
923             };
924             if new_parent.kind.get() != NormalModuleKind {
925                 modifiers = modifiers & !IMPORTABLE;
926             }
927             child_name_bindings.define_value(def, DUMMY_SP, modifiers);
928           }
929           DefTrait(def_id) => {
930               debug!("(building reduced graph for external \
931                       crate) building type {}", final_ident);
932
933               // If this is a trait, add all the trait item names to the trait
934               // info.
935
936               let trait_item_def_ids =
937                 csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
938               for trait_item_def_id in trait_item_def_ids.iter() {
939                   let (trait_item_name, trait_item_kind) =
940                       csearch::get_trait_item_name_and_kind(
941                           &self.session.cstore,
942                           trait_item_def_id.def_id());
943
944                   debug!("(building reduced graph for external crate) ... \
945                           adding trait item '{}'",
946                          token::get_name(trait_item_name));
947
948                   self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind);
949
950                   if is_exported {
951                       self.external_exports
952                           .insert(trait_item_def_id.def_id());
953                   }
954               }
955
956               child_name_bindings.define_type(def, DUMMY_SP, modifiers);
957
958               // Define a module if necessary.
959               let parent_link = self.get_parent_link(new_parent, name);
960               child_name_bindings.set_module_kind(parent_link,
961                                                   Some(def_id),
962                                                   TraitModuleKind,
963                                                   true,
964                                                   is_public,
965                                                   DUMMY_SP)
966           }
967           DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => {
968               debug!("(building reduced graph for external \
969                       crate) building type {}", final_ident);
970
971               child_name_bindings.define_type(def, DUMMY_SP, modifiers);
972           }
973           DefStruct(def_id) => {
974             debug!("(building reduced graph for external \
975                     crate) building type and value for {}",
976                    final_ident);
977             child_name_bindings.define_type(def, DUMMY_SP, modifiers);
978             let fields = csearch::get_struct_fields(&self.session.cstore, def_id).iter().map(|f| {
979                 f.name
980             }).collect::<Vec<_>>();
981
982             if fields.len() == 0 {
983                 child_name_bindings.define_value(def, DUMMY_SP, modifiers);
984             }
985
986             // Record the def ID and fields of this struct.
987             self.structs.insert(def_id, fields);
988           }
989           DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
990           DefUse(..) | DefUpvar(..) | DefRegion(..) |
991           DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
992             panic!("didn't expect `{}`", def);
993           }
994         }
995     }
996
997     /// Builds the reduced graph for a single item in an external crate.
998     fn build_reduced_graph_for_external_crate_def(&mut self,
999                                                   root: &Rc<Module>,
1000                                                   def_like: DefLike,
1001                                                   name: Name,
1002                                                   visibility: Visibility) {
1003         match def_like {
1004             DlDef(def) => {
1005                 // Add the new child item, if necessary.
1006                 match def {
1007                     DefForeignMod(def_id) => {
1008                         // Foreign modules have no names. Recur and populate
1009                         // eagerly.
1010                         csearch::each_child_of_item(&self.session.cstore,
1011                                                     def_id,
1012                                                     |def_like,
1013                                                      child_name,
1014                                                      vis| {
1015                             self.build_reduced_graph_for_external_crate_def(
1016                                 root,
1017                                 def_like,
1018                                 child_name,
1019                                 vis)
1020                         });
1021                     }
1022                     _ => {
1023                         let child_name_bindings =
1024                             self.add_child(name,
1025                                            root,
1026                                            OverwriteDuplicates,
1027                                            DUMMY_SP);
1028
1029                         self.handle_external_def(def,
1030                                                  visibility,
1031                                                  &*child_name_bindings,
1032                                                  token::get_name(name).get(),
1033                                                  name,
1034                                                  root);
1035                     }
1036                 }
1037             }
1038             DlImpl(def) => {
1039                 match csearch::get_type_name_if_impl(&self.session.cstore, def) {
1040                     None => {}
1041                     Some(final_name) => {
1042                         let methods_opt =
1043                             csearch::get_methods_if_impl(&self.session.cstore, def);
1044                         match methods_opt {
1045                             Some(ref methods) if
1046                                 methods.len() >= 1 => {
1047                                 debug!("(building reduced graph for \
1048                                         external crate) processing \
1049                                         static methods for type name {}",
1050                                         token::get_name(final_name));
1051
1052                                 let child_name_bindings =
1053                                     self.add_child(
1054                                         final_name,
1055                                         root,
1056                                         OverwriteDuplicates,
1057                                         DUMMY_SP);
1058
1059                                 // Process the static methods. First,
1060                                 // create the module.
1061                                 let type_module;
1062                                 let type_def = child_name_bindings.type_def.borrow().clone();
1063                                 match type_def {
1064                                     Some(TypeNsDef {
1065                                         module_def: Some(module_def),
1066                                         ..
1067                                     }) => {
1068                                         // We already have a module. This
1069                                         // is OK.
1070                                         type_module = module_def;
1071
1072                                         // Mark it as an impl module if
1073                                         // necessary.
1074                                         type_module.kind.set(ImplModuleKind);
1075                                     }
1076                                     Some(_) | None => {
1077                                         let parent_link =
1078                                             self.get_parent_link(root, final_name);
1079                                         child_name_bindings.define_module(
1080                                             parent_link,
1081                                             Some(def),
1082                                             ImplModuleKind,
1083                                             true,
1084                                             true,
1085                                             DUMMY_SP);
1086                                         type_module =
1087                                             child_name_bindings.
1088                                                 get_module();
1089                                     }
1090                                 }
1091
1092                                 // Add each static method to the module.
1093                                 let new_parent = type_module;
1094                                 for method_info in methods.iter() {
1095                                     let name = method_info.name;
1096                                     debug!("(building reduced graph for \
1097                                              external crate) creating \
1098                                              static method '{}'",
1099                                            token::get_name(name));
1100
1101                                     let method_name_bindings =
1102                                         self.add_child(name,
1103                                                        &new_parent,
1104                                                        OverwriteDuplicates,
1105                                                        DUMMY_SP);
1106                                     let def = DefFn(method_info.def_id, false);
1107
1108                                     // NB: not IMPORTABLE
1109                                     let modifiers = if visibility == ast::Public {
1110                                         PUBLIC
1111                                     } else {
1112                                         DefModifiers::empty()
1113                                     };
1114                                     method_name_bindings.define_value(
1115                                         def, DUMMY_SP, modifiers);
1116                                 }
1117                             }
1118
1119                             // Otherwise, do nothing.
1120                             Some(_) | None => {}
1121                         }
1122                     }
1123                 }
1124             }
1125             DlField => {
1126                 debug!("(building reduced graph for external crate) \
1127                         ignoring field");
1128             }
1129         }
1130     }
1131
1132     /// Builds the reduced graph rooted at the given external module.
1133     fn populate_external_module(&mut self, module: &Rc<Module>) {
1134         debug!("(populating external module) attempting to populate {}",
1135                self.module_to_string(&**module));
1136
1137         let def_id = match module.def_id.get() {
1138             None => {
1139                 debug!("(populating external module) ... no def ID!");
1140                 return
1141             }
1142             Some(def_id) => def_id,
1143         };
1144
1145         csearch::each_child_of_item(&self.session.cstore,
1146                                     def_id,
1147                                     |def_like, child_name, visibility| {
1148             debug!("(populating external module) ... found ident: {}",
1149                    token::get_name(child_name));
1150             self.build_reduced_graph_for_external_crate_def(module,
1151                                                             def_like,
1152                                                             child_name,
1153                                                             visibility)
1154         });
1155         module.populated.set(true)
1156     }
1157
1158     /// Ensures that the reduced graph rooted at the given external module
1159     /// is built, building it if it is not.
1160     fn populate_module_if_necessary(&mut self, module: &Rc<Module>) {
1161         if !module.populated.get() {
1162             self.populate_external_module(module)
1163         }
1164         assert!(module.populated.get())
1165     }
1166
1167     /// Builds the reduced graph rooted at the 'use' directive for an external
1168     /// crate.
1169     fn build_reduced_graph_for_external_crate(&mut self, root: &Rc<Module>) {
1170         csearch::each_top_level_item_of_crate(&self.session.cstore,
1171                                               root.def_id
1172                                                   .get()
1173                                                   .unwrap()
1174                                                   .krate,
1175                                               |def_like, name, visibility| {
1176             self.build_reduced_graph_for_external_crate_def(root, def_like, name, visibility)
1177         });
1178     }
1179
1180     /// Creates and adds an import directive to the given module.
1181     fn build_import_directive(&mut self,
1182                               module_: &Module,
1183                               module_path: Vec<Name>,
1184                               subclass: ImportDirectiveSubclass,
1185                               span: Span,
1186                               id: NodeId,
1187                               is_public: bool,
1188                               shadowable: Shadowable) {
1189         module_.imports.borrow_mut().push(ImportDirective::new(module_path,
1190                                                                subclass,
1191                                                                span,
1192                                                                id,
1193                                                                is_public,
1194                                                                shadowable));
1195         self.unresolved_imports += 1;
1196         // Bump the reference count on the name. Or, if this is a glob, set
1197         // the appropriate flag.
1198
1199         match subclass {
1200             SingleImport(target, _) => {
1201                 debug!("(building import directive) building import \
1202                         directive: {}::{}",
1203                        self.names_to_string(module_.imports.borrow().last().unwrap()
1204                                                  .module_path[]),
1205                        token::get_name(target));
1206
1207                 let mut import_resolutions = module_.import_resolutions
1208                                                     .borrow_mut();
1209                 match import_resolutions.get_mut(&target) {
1210                     Some(resolution) => {
1211                         debug!("(building import directive) bumping \
1212                                 reference");
1213                         resolution.outstanding_references += 1;
1214
1215                         // the source of this name is different now
1216                         resolution.type_id = id;
1217                         resolution.value_id = id;
1218                         resolution.is_public = is_public;
1219                         return;
1220                     }
1221                     None => {}
1222                 }
1223                 debug!("(building import directive) creating new");
1224                 let mut resolution = ImportResolution::new(id, is_public);
1225                 resolution.outstanding_references = 1;
1226                 import_resolutions.insert(target, resolution);
1227             }
1228             GlobImport => {
1229                 // Set the glob flag. This tells us that we don't know the
1230                 // module's exports ahead of time.
1231
1232                 module_.glob_count.set(module_.glob_count.get() + 1);
1233             }
1234         }
1235     }
1236 }
1237
1238 struct BuildReducedGraphVisitor<'a, 'b:'a, 'tcx:'b> {
1239     builder: GraphBuilder<'a, 'b, 'tcx>,
1240     parent: Rc<Module>
1241 }
1242
1243 impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
1244     fn visit_item(&mut self, item: &Item) {
1245         let p = self.builder.build_reduced_graph_for_item(item, &self.parent);
1246         let old_parent = replace(&mut self.parent, p);
1247         visit::walk_item(self, item);
1248         self.parent = old_parent;
1249     }
1250
1251     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
1252         let parent = &self.parent;
1253         self.builder.build_reduced_graph_for_foreign_item(foreign_item,
1254                                                           parent,
1255                                                           |r| {
1256             let mut v = BuildReducedGraphVisitor {
1257                 builder: GraphBuilder { resolver: r },
1258                 parent: parent.clone()
1259             };
1260             visit::walk_foreign_item(&mut v, foreign_item);
1261         })
1262     }
1263
1264     fn visit_view_item(&mut self, view_item: &ViewItem) {
1265         self.builder.build_reduced_graph_for_view_item(view_item, &self.parent);
1266     }
1267
1268     fn visit_block(&mut self, block: &Block) {
1269         let np = self.builder.build_reduced_graph_for_block(block, &self.parent);
1270         let old_parent = replace(&mut self.parent, np);
1271         visit::walk_block(self, block);
1272         self.parent = old_parent;
1273     }
1274 }
1275
1276 pub fn build_reduced_graph(resolver: &mut Resolver, krate: &ast::Crate) {
1277     GraphBuilder {
1278         resolver: resolver
1279     }.build_reduced_graph(krate);
1280 }
1281
1282 pub fn populate_module_if_necessary(resolver: &mut Resolver, module: &Rc<Module>) {
1283     GraphBuilder {
1284         resolver: resolver
1285     }.populate_module_if_necessary(module);
1286 }