]> git.lizzy.rs Git - rust.git/blob - src/librustc_resolve/build_reduced_graph.rs
21eec383df465508d99304f6ea6f14b1f8c96421
[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,
325                                    sp);
326
327                 name_bindings.define_type(DefTy(local_def(item.id), false), sp,
328                                           modifiers);
329
330                 let parent_link = self.get_parent_link(parent, name);
331                 name_bindings.set_module_kind(parent_link,
332                                               Some(local_def(item.id)),
333                                               TypeModuleKind,
334                                               false,
335                                               is_public,
336                                               sp);
337                 parent.clone()
338             }
339
340             ItemEnum(ref enum_definition, _) => {
341                 let name_bindings =
342                     self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
343
344                 name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers);
345
346                 let parent_link = self.get_parent_link(parent, name);
347                 // We want to make sure the module type is EnumModuleKind
348                 // even if there's already an ImplModuleKind module defined,
349                 // since that's how we prevent duplicate enum definitions
350                 name_bindings.set_module_kind(parent_link,
351                                               Some(local_def(item.id)),
352                                               EnumModuleKind,
353                                               false,
354                                               is_public,
355                                               sp);
356
357                 let module = name_bindings.get_module();
358
359                 for variant in (*enum_definition).variants.iter() {
360                     self.build_reduced_graph_for_variant(
361                         &**variant,
362                         local_def(item.id),
363                         &module);
364                 }
365                 parent.clone()
366             }
367
368             // These items live in both the type and value namespaces.
369             ItemStruct(ref struct_def, _) => {
370                 // Adding to both Type and Value namespaces or just Type?
371                 let (forbid, ctor_id) = match struct_def.ctor_id {
372                     Some(ctor_id)   => (ForbidDuplicateTypesAndValues, Some(ctor_id)),
373                     None            => (ForbidDuplicateTypesAndModules, None)
374                 };
375
376                 let name_bindings = self.add_child(name, parent, forbid, sp);
377
378                 // Define a name in the type namespace.
379                 name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers);
380
381                 // If this is a newtype or unit-like struct, define a name
382                 // in the value namespace as well
383                 if let Some(cid) = ctor_id {
384                     name_bindings.define_value(DefStruct(local_def(cid)), sp, modifiers);
385                 }
386
387                 // Record the def ID and fields of this struct.
388                 let named_fields = struct_def.fields.iter().filter_map(|f| {
389                     match f.node.kind {
390                         NamedField(ident, _) => Some(ident.name),
391                         UnnamedField(_) => None
392                     }
393                 }).collect();
394                 self.structs.insert(local_def(item.id), named_fields);
395
396                 parent.clone()
397             }
398
399             ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
400                 // If this implements an anonymous trait, then add all the
401                 // methods within to a new module, if the type was defined
402                 // within this module.
403
404                 let mod_name = match ty.node {
405                     TyPath(ref path, _) if path.segments.len() == 1 => {
406                         // FIXME(18446) we should distinguish between the name of
407                         // a trait and the name of an impl of that trait.
408                         Some(path.segments.last().unwrap().identifier.name)
409                     }
410                     TyObjectSum(ref lhs_ty, _) => {
411                         match lhs_ty.node {
412                             TyPath(ref path, _) if path.segments.len() == 1 => {
413                                 Some(path.segments.last().unwrap().identifier.name)
414                             }
415                             _ => {
416                                 None
417                             }
418                         }
419                     }
420                     _ => {
421                         None
422                     }
423                 };
424
425                 let mod_name = match mod_name {
426                     Some(mod_name) => mod_name,
427                     None => {
428                         self.resolve_error(ty.span,
429                                            "inherent implementations may \
430                                             only be implemented in the same \
431                                             module as the type they are \
432                                             implemented for");
433                         return parent.clone();
434                     }
435                 };
436                 // Create the module and add all methods.
437                 let child_opt = parent.children.borrow().get(&mod_name)
438                                        .and_then(|m| m.get_module_if_available());
439                 let new_parent = match child_opt {
440                     // It already exists
441                     Some(ref child) if (child.kind.get() == ImplModuleKind ||
442                                         child.kind.get() == TraitModuleKind) => {
443                         child.clone()
444                     }
445                     Some(ref child) if child.kind.get() == EnumModuleKind ||
446                                        child.kind.get() == TypeModuleKind => {
447                         child.clone()
448                     }
449                     // Create the module
450                     _ => {
451                         let name_bindings =
452                             self.add_child(mod_name, parent, ForbidDuplicateModules, sp);
453
454                         let parent_link = self.get_parent_link(parent, name);
455                         let def_id = local_def(item.id);
456                         let ns = TypeNS;
457                         let is_public =
458                             !name_bindings.defined_in_namespace(ns) ||
459                             name_bindings.defined_in_public_namespace(ns);
460
461                         name_bindings.define_module(parent_link,
462                                                     Some(def_id),
463                                                     ImplModuleKind,
464                                                     false,
465                                                     is_public,
466                                                     sp);
467
468                         name_bindings.get_module()
469                     }
470                 };
471
472                 // For each implementation item...
473                 for impl_item in impl_items.iter() {
474                     match *impl_item {
475                         MethodImplItem(ref method) => {
476                             // Add the method to the module.
477                             let name = method.pe_ident().name;
478                             let method_name_bindings =
479                                 self.add_child(name,
480                                                &new_parent,
481                                                ForbidDuplicateValues,
482                                                method.span);
483                             let def = match method.pe_explicit_self()
484                                 .node {
485                                     SelfStatic => {
486                                         // Static methods become
487                                         // `DefStaticMethod`s.
488                                         DefStaticMethod(local_def(method.id),
489                                                         FromImpl(local_def(item.id)))
490                                     }
491                                     _ => {
492                                         // Non-static methods become
493                                         // `DefMethod`s.
494                                         DefMethod(local_def(method.id),
495                                                   None,
496                                                   FromImpl(local_def(item.id)))
497                                     }
498                                 };
499
500                             // NB: not IMPORTABLE
501                             let modifiers = if method.pe_vis() == ast::Public {
502                                 PUBLIC
503                             } else {
504                                 DefModifiers::empty()
505                             };
506                             method_name_bindings.define_value(
507                                 def,
508                                 method.span,
509                                 modifiers);
510                         }
511                         TypeImplItem(ref typedef) => {
512                             // Add the typedef to the module.
513                             let name = typedef.ident.name;
514                             let typedef_name_bindings =
515                                 self.add_child(
516                                     name,
517                                     &new_parent,
518                                     ForbidDuplicateTypesAndModules,
519                                     typedef.span);
520                             let def = DefAssociatedTy(local_def(
521                                 typedef.id));
522                             // NB: not IMPORTABLE
523                             let modifiers = if typedef.vis == ast::Public {
524                                 PUBLIC
525                             } else {
526                                 DefModifiers::empty()
527                             };
528                             typedef_name_bindings.define_type(
529                                 def,
530                                 typedef.span,
531                                 modifiers);
532                         }
533                     }
534                 }
535                 parent.clone()
536             }
537
538             ItemImpl(_, _, _, Some(_), _, _) => parent.clone(),
539
540             ItemTrait(_, _, _, ref items) => {
541                 let name_bindings =
542                     self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
543
544                 // Add all the items within to a new module.
545                 let parent_link = self.get_parent_link(parent, name);
546                 name_bindings.define_module(parent_link,
547                                             Some(local_def(item.id)),
548                                             TraitModuleKind,
549                                             false,
550                                             item.vis == ast::Public,
551                                             sp);
552                 let module_parent = name_bindings.get_module();
553
554                 let def_id = local_def(item.id);
555
556                 // Add the names of all the items to the trait info.
557                 for trait_item in items.iter() {
558                     let (name, kind) = match *trait_item {
559                         ast::RequiredMethod(_) |
560                         ast::ProvidedMethod(_) => {
561                             let ty_m = ast_util::trait_item_to_ty_method(trait_item);
562
563                             let name = ty_m.ident.name;
564
565                             // Add it as a name in the trait module.
566                             let (def, static_flag) = match ty_m.explicit_self
567                                                                .node {
568                                 SelfStatic => {
569                                     // Static methods become `DefStaticMethod`s.
570                                     (DefStaticMethod(
571                                             local_def(ty_m.id),
572                                             FromTrait(local_def(item.id))),
573                                      StaticMethodTraitItemKind)
574                                 }
575                                 _ => {
576                                     // Non-static methods become `DefMethod`s.
577                                     (DefMethod(local_def(ty_m.id),
578                                                Some(local_def(item.id)),
579                                                FromTrait(local_def(item.id))),
580                                      NonstaticMethodTraitItemKind)
581                                 }
582                             };
583
584                             let method_name_bindings =
585                                 self.add_child(name,
586                                                &module_parent,
587                                                ForbidDuplicateTypesAndValues,
588                                                ty_m.span);
589                             // NB: not IMPORTABLE
590                             method_name_bindings.define_value(def,
591                                                               ty_m.span,
592                                                               PUBLIC);
593
594                             (name, static_flag)
595                         }
596                         ast::TypeTraitItem(ref associated_type) => {
597                             let def = DefAssociatedTy(local_def(
598                                     associated_type.ty_param.id));
599
600                             let name_bindings =
601                                 self.add_child(associated_type.ty_param.ident.name,
602                                                &module_parent,
603                                                ForbidDuplicateTypesAndValues,
604                                                associated_type.ty_param.span);
605                             // NB: not IMPORTABLE
606                             name_bindings.define_type(def,
607                                                       associated_type.ty_param.span,
608                                                       PUBLIC);
609
610                             (associated_type.ty_param.ident.name, TypeTraitItemKind)
611                         }
612                     };
613
614                     self.trait_item_map.insert((name, def_id), kind);
615                 }
616
617                 name_bindings.define_type(DefTrait(def_id), sp, modifiers);
618                 parent.clone()
619             }
620             ItemMac(..) => parent.clone()
621         }
622     }
623
624     // Constructs the reduced graph for one variant. Variants exist in the
625     // type and value namespaces.
626     fn build_reduced_graph_for_variant(&mut self,
627                                        variant: &Variant,
628                                        item_id: DefId,
629                                        parent: &Rc<Module>) {
630         let name = variant.node.name.name;
631         let is_exported = match variant.node.kind {
632             TupleVariantKind(_) => false,
633             StructVariantKind(_) => {
634                 // Not adding fields for variants as they are not accessed with a self receiver
635                 self.structs.insert(local_def(variant.node.id), Vec::new());
636                 true
637             }
638         };
639
640         let child = self.add_child(name, parent,
641                                    ForbidDuplicateTypesAndValues,
642                                    variant.span);
643         // variants are always treated as importable to allow them to be glob
644         // used
645         child.define_value(DefVariant(item_id,
646                                       local_def(variant.node.id), is_exported),
647                            variant.span, PUBLIC | IMPORTABLE);
648         child.define_type(DefVariant(item_id,
649                                      local_def(variant.node.id), is_exported),
650                           variant.span, PUBLIC | IMPORTABLE);
651     }
652
653     /// Constructs the reduced graph for one 'view item'. View items consist
654     /// of imports and use directives.
655     fn build_reduced_graph_for_view_item(&mut self, view_item: &ViewItem, parent: &Rc<Module>) {
656         match view_item.node {
657             ViewItemUse(ref view_path) => {
658                 // Extract and intern the module part of the path. For
659                 // globs and lists, the path is found directly in the AST;
660                 // for simple paths we have to munge the path a little.
661                 let module_path = match view_path.node {
662                     ViewPathSimple(_, ref full_path, _) => {
663                         full_path.segments
664                             .init()
665                             .iter().map(|ident| ident.identifier.name)
666                             .collect()
667                     }
668
669                     ViewPathGlob(ref module_ident_path, _) |
670                     ViewPathList(ref module_ident_path, _, _) => {
671                         module_ident_path.segments
672                             .iter().map(|ident| ident.identifier.name).collect()
673                     }
674                 };
675
676                 // Build up the import directives.
677                 let is_public = view_item.vis == ast::Public;
678                 let shadowable =
679                     view_item.attrs
680                              .iter()
681                              .any(|attr| {
682                                  attr.name() == token::get_name(
683                                     special_idents::prelude_import.name)
684                              });
685                 let shadowable = if shadowable {
686                     Shadowable::Always
687                 } else {
688                     Shadowable::Never
689                 };
690
691                 match view_path.node {
692                     ViewPathSimple(binding, ref full_path, id) => {
693                         let source_name =
694                             full_path.segments.last().unwrap().identifier.name;
695                         if token::get_name(source_name).get() == "mod" ||
696                            token::get_name(source_name).get() == "self" {
697                             self.resolve_error(view_path.span,
698                                 "`self` imports are only allowed within a { } list");
699                         }
700
701                         let subclass = SingleImport(binding.name,
702                                                     source_name);
703                         self.build_import_directive(&**parent,
704                                                     module_path,
705                                                     subclass,
706                                                     view_path.span,
707                                                     id,
708                                                     is_public,
709                                                     shadowable);
710                     }
711                     ViewPathList(_, ref source_items, _) => {
712                         // Make sure there's at most one `mod` import in the list.
713                         let mod_spans = source_items.iter().filter_map(|item| match item.node {
714                             PathListMod { .. } => Some(item.span),
715                             _ => None
716                         }).collect::<Vec<Span>>();
717                         if mod_spans.len() > 1 {
718                             self.resolve_error(mod_spans[0],
719                                 "`self` import can only appear once in the list");
720                             for other_span in mod_spans.iter().skip(1) {
721                                 self.session.span_note(*other_span,
722                                     "another `self` import appears here");
723                             }
724                         }
725
726                         for source_item in source_items.iter() {
727                             let (module_path, name) = match source_item.node {
728                                 PathListIdent { name, .. } =>
729                                     (module_path.clone(), name.name),
730                                 PathListMod { .. } => {
731                                     let name = match module_path.last() {
732                                         Some(name) => *name,
733                                         None => {
734                                             self.resolve_error(source_item.span,
735                                                 "`self` import can only appear in an import list \
736                                                  with a non-empty prefix");
737                                             continue;
738                                         }
739                                     };
740                                     let module_path = module_path.init();
741                                     (module_path.to_vec(), name)
742                                 }
743                             };
744                             self.build_import_directive(
745                                 &**parent,
746                                 module_path,
747                                 SingleImport(name, name),
748                                 source_item.span,
749                                 source_item.node.id(),
750                                 is_public,
751                                 shadowable);
752                         }
753                     }
754                     ViewPathGlob(_, id) => {
755                         self.build_import_directive(&**parent,
756                                                     module_path,
757                                                     GlobImport,
758                                                     view_path.span,
759                                                     id,
760                                                     is_public,
761                                                     shadowable);
762                     }
763                 }
764             }
765
766             ViewItemExternCrate(name, _, node_id) => {
767                 // n.b. we don't need to look at the path option here, because cstore already did
768                 for &crate_id in self.session.cstore
769                                      .find_extern_mod_stmt_cnum(node_id).iter() {
770                     let def_id = DefId { krate: crate_id, node: 0 };
771                     self.external_exports.insert(def_id);
772                     let parent_link = ModuleParentLink(parent.downgrade(), name.name);
773                     let external_module = Rc::new(Module::new(parent_link,
774                                                               Some(def_id),
775                                                               NormalModuleKind,
776                                                               false,
777                                                               true));
778                     debug!("(build reduced graph for item) found extern `{}`",
779                             self.module_to_string(&*external_module));
780                     self.check_for_conflicts_between_external_crates(
781                         &**parent,
782                         name.name,
783                         view_item.span);
784                     parent.external_module_children.borrow_mut()
785                           .insert(name.name, external_module.clone());
786                     self.build_reduced_graph_for_external_crate(&external_module);
787                 }
788             }
789         }
790     }
791
792     /// Constructs the reduced graph for one foreign item.
793     fn build_reduced_graph_for_foreign_item<F>(&mut self,
794                                                foreign_item: &ForeignItem,
795                                                parent: &Rc<Module>,
796                                                f: F) where
797         F: FnOnce(&mut Resolver),
798     {
799         let name = foreign_item.ident.name;
800         let is_public = foreign_item.vis == ast::Public;
801         let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
802         let name_bindings =
803             self.add_child(name, parent, ForbidDuplicateValues,
804                            foreign_item.span);
805
806         match foreign_item.node {
807             ForeignItemFn(_, ref generics) => {
808                 let def = DefFn(local_def(foreign_item.id), false);
809                 name_bindings.define_value(def, foreign_item.span, modifiers);
810
811                 self.with_type_parameter_rib(
812                     HasTypeParameters(generics,
813                                       FnSpace,
814                                       foreign_item.id,
815                                       NormalRibKind),
816                     f);
817             }
818             ForeignItemStatic(_, m) => {
819                 let def = DefStatic(local_def(foreign_item.id), m);
820                 name_bindings.define_value(def, foreign_item.span, modifiers);
821
822                 f(self.resolver)
823             }
824         }
825     }
826
827     fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc<Module>) -> Rc<Module> {
828         if self.block_needs_anonymous_module(block) {
829             let block_id = block.id;
830
831             debug!("(building reduced graph for block) creating a new \
832                     anonymous module for block {}",
833                    block_id);
834
835             let new_module = Rc::new(Module::new(
836                 BlockParentLink(parent.downgrade(), block_id),
837                 None,
838                 AnonymousModuleKind,
839                 false,
840                 false));
841             parent.anonymous_children.borrow_mut().insert(block_id, new_module.clone());
842             new_module
843         } else {
844             parent.clone()
845         }
846     }
847
848     fn handle_external_def(&mut self,
849                            def: Def,
850                            vis: Visibility,
851                            child_name_bindings: &NameBindings,
852                            final_ident: &str,
853                            name: Name,
854                            new_parent: &Rc<Module>) {
855         debug!("(building reduced graph for \
856                 external crate) building external def, priv {:?}",
857                vis);
858         let is_public = vis == ast::Public;
859         let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
860         let is_exported = is_public && match new_parent.def_id.get() {
861             None => true,
862             Some(did) => self.external_exports.contains(&did)
863         };
864         if is_exported {
865             self.external_exports.insert(def.def_id());
866         }
867
868         let kind = match def {
869             DefTy(_, true) => EnumModuleKind,
870             DefTy(_, false) => TypeModuleKind,
871             DefStruct(..) => ImplModuleKind,
872             _ => NormalModuleKind
873         };
874
875         match def {
876           DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) |
877           DefTy(def_id, _) => {
878             let type_def = child_name_bindings.type_def.borrow().clone();
879             match type_def {
880               Some(TypeNsDef { module_def: Some(module_def), .. }) => {
881                 debug!("(building reduced graph for external crate) \
882                         already created module");
883                 module_def.def_id.set(Some(def_id));
884               }
885               Some(_) | None => {
886                 debug!("(building reduced graph for \
887                         external crate) building module \
888                         {}", final_ident);
889                 let parent_link = self.get_parent_link(new_parent, name);
890
891                 child_name_bindings.define_module(parent_link,
892                                                   Some(def_id),
893                                                   kind,
894                                                   true,
895                                                   is_public,
896                                                   DUMMY_SP);
897               }
898             }
899           }
900           _ => {}
901         }
902
903         match def {
904           DefMod(_) | DefForeignMod(_) => {}
905           DefVariant(_, variant_id, is_struct) => {
906               debug!("(building reduced graph for external crate) building \
907                       variant {}",
908                       final_ident);
909               // variants are always treated as importable to allow them to be
910               // glob used
911               let modifiers = PUBLIC | IMPORTABLE;
912               if is_struct {
913                   child_name_bindings.define_type(def, DUMMY_SP, modifiers);
914                   // Not adding fields for variants as they are not accessed with a self receiver
915                   self.structs.insert(variant_id, Vec::new());
916               } else {
917                   child_name_bindings.define_value(def, DUMMY_SP, modifiers);
918               }
919           }
920           DefFn(ctor_id, true) => {
921             child_name_bindings.define_value(
922                 csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
923                     .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
924           }
925           DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
926             debug!("(building reduced graph for external \
927                     crate) building value (fn/static) {}", final_ident);
928             // impl methods have already been defined with the correct importability modifier
929             let mut modifiers = match *child_name_bindings.value_def.borrow() {
930                 Some(ref def) => (modifiers & !IMPORTABLE) | (def.modifiers & IMPORTABLE),
931                 None => modifiers
932             };
933             if new_parent.kind.get() != NormalModuleKind {
934                 modifiers = modifiers & !IMPORTABLE;
935             }
936             child_name_bindings.define_value(def, DUMMY_SP, modifiers);
937           }
938           DefTrait(def_id) => {
939               debug!("(building reduced graph for external \
940                       crate) building type {}", final_ident);
941
942               // If this is a trait, add all the trait item names to the trait
943               // info.
944
945               let trait_item_def_ids =
946                 csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
947               for trait_item_def_id in trait_item_def_ids.iter() {
948                   let (trait_item_name, trait_item_kind) =
949                       csearch::get_trait_item_name_and_kind(
950                           &self.session.cstore,
951                           trait_item_def_id.def_id());
952
953                   debug!("(building reduced graph for external crate) ... \
954                           adding trait item '{}'",
955                          token::get_name(trait_item_name));
956
957                   self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind);
958
959                   if is_exported {
960                       self.external_exports
961                           .insert(trait_item_def_id.def_id());
962                   }
963               }
964
965               child_name_bindings.define_type(def, DUMMY_SP, modifiers);
966
967               // Define a module if necessary.
968               let parent_link = self.get_parent_link(new_parent, name);
969               child_name_bindings.set_module_kind(parent_link,
970                                                   Some(def_id),
971                                                   TraitModuleKind,
972                                                   true,
973                                                   is_public,
974                                                   DUMMY_SP)
975           }
976           DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => {
977               debug!("(building reduced graph for external \
978                       crate) building type {}", final_ident);
979
980               child_name_bindings.define_type(def, DUMMY_SP, modifiers);
981           }
982           DefStruct(def_id) => {
983             debug!("(building reduced graph for external \
984                     crate) building type and value for {}",
985                    final_ident);
986             child_name_bindings.define_type(def, DUMMY_SP, modifiers);
987             let fields = csearch::get_struct_fields(&self.session.cstore, def_id).iter().map(|f| {
988                 f.name
989             }).collect::<Vec<_>>();
990
991             if fields.len() == 0 {
992                 child_name_bindings.define_value(def, DUMMY_SP, modifiers);
993             }
994
995             // Record the def ID and fields of this struct.
996             self.structs.insert(def_id, fields);
997           }
998           DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
999           DefUse(..) | DefUpvar(..) | DefRegion(..) |
1000           DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
1001             panic!("didn't expect `{:?}`", def);
1002           }
1003         }
1004     }
1005
1006     /// Builds the reduced graph for a single item in an external crate.
1007     fn build_reduced_graph_for_external_crate_def(&mut self,
1008                                                   root: &Rc<Module>,
1009                                                   def_like: DefLike,
1010                                                   name: Name,
1011                                                   def_visibility: Visibility) {
1012         match def_like {
1013             DlDef(def) => {
1014                 // Add the new child item, if necessary.
1015                 match def {
1016                     DefForeignMod(def_id) => {
1017                         // Foreign modules have no names. Recur and populate
1018                         // eagerly.
1019                         csearch::each_child_of_item(&self.session.cstore,
1020                                                     def_id,
1021                                                     |def_like,
1022                                                      child_name,
1023                                                      vis| {
1024                             self.build_reduced_graph_for_external_crate_def(
1025                                 root,
1026                                 def_like,
1027                                 child_name,
1028                                 vis)
1029                         });
1030                     }
1031                     _ => {
1032                         let child_name_bindings =
1033                             self.add_child(name,
1034                                            root,
1035                                            OverwriteDuplicates,
1036                                            DUMMY_SP);
1037
1038                         self.handle_external_def(def,
1039                                                  def_visibility,
1040                                                  &*child_name_bindings,
1041                                                  token::get_name(name).get(),
1042                                                  name,
1043                                                  root);
1044                     }
1045                 }
1046             }
1047             DlImpl(def) => {
1048                 match csearch::get_type_name_if_impl(&self.session.cstore, def) {
1049                     None => {}
1050                     Some(final_name) => {
1051                         let methods_opt =
1052                             csearch::get_methods_if_impl(&self.session.cstore, def);
1053                         match methods_opt {
1054                             Some(ref methods) if
1055                                 methods.len() >= 1 => {
1056                                 debug!("(building reduced graph for \
1057                                         external crate) processing \
1058                                         static methods for type name {}",
1059                                         token::get_name(final_name));
1060
1061                                 let child_name_bindings =
1062                                     self.add_child(
1063                                         final_name,
1064                                         root,
1065                                         OverwriteDuplicates,
1066                                         DUMMY_SP);
1067
1068                                 // Process the static methods. First,
1069                                 // create the module.
1070                                 let type_module;
1071                                 let type_def = child_name_bindings.type_def.borrow().clone();
1072                                 match type_def {
1073                                     Some(TypeNsDef {
1074                                         module_def: Some(module_def),
1075                                         ..
1076                                     }) => {
1077                                         // We already have a module. This
1078                                         // is OK.
1079                                         type_module = module_def;
1080
1081                                         // Mark it as an impl module if
1082                                         // necessary.
1083                                         type_module.kind.set(ImplModuleKind);
1084                                     }
1085                                     Some(_) | None => {
1086                                         let parent_link =
1087                                             self.get_parent_link(root, final_name);
1088                                         child_name_bindings.define_module(
1089                                             parent_link,
1090                                             Some(def),
1091                                             ImplModuleKind,
1092                                             true,
1093                                             true,
1094                                             DUMMY_SP);
1095                                         type_module =
1096                                             child_name_bindings.
1097                                                 get_module();
1098                                     }
1099                                 }
1100
1101                                 // Add each static method to the module.
1102                                 let new_parent = type_module;
1103                                 for method_info in methods.iter() {
1104                                     let name = method_info.name;
1105                                     debug!("(building reduced graph for \
1106                                              external crate) creating \
1107                                              static method '{}'",
1108                                            token::get_name(name));
1109
1110                                     let method_name_bindings =
1111                                         self.add_child(name,
1112                                                        &new_parent,
1113                                                        OverwriteDuplicates,
1114                                                        DUMMY_SP);
1115                                     let def = DefFn(method_info.def_id, false);
1116
1117                                     // NB: not IMPORTABLE
1118                                     let modifiers = if method_info.vis == ast::Public {
1119                                         PUBLIC
1120                                     } else {
1121                                         DefModifiers::empty()
1122                                     };
1123                                     method_name_bindings.define_value(
1124                                         def, DUMMY_SP, modifiers);
1125                                 }
1126                             }
1127
1128                             // Otherwise, do nothing.
1129                             Some(_) | None => {}
1130                         }
1131                     }
1132                 }
1133             }
1134             DlField => {
1135                 debug!("(building reduced graph for external crate) \
1136                         ignoring field");
1137             }
1138         }
1139     }
1140
1141     /// Builds the reduced graph rooted at the given external module.
1142     fn populate_external_module(&mut self, module: &Rc<Module>) {
1143         debug!("(populating external module) attempting to populate {}",
1144                self.module_to_string(&**module));
1145
1146         let def_id = match module.def_id.get() {
1147             None => {
1148                 debug!("(populating external module) ... no def ID!");
1149                 return
1150             }
1151             Some(def_id) => def_id,
1152         };
1153
1154         csearch::each_child_of_item(&self.session.cstore,
1155                                     def_id,
1156                                     |def_like, child_name, visibility| {
1157             debug!("(populating external module) ... found ident: {}",
1158                    token::get_name(child_name));
1159             self.build_reduced_graph_for_external_crate_def(module,
1160                                                             def_like,
1161                                                             child_name,
1162                                                             visibility)
1163         });
1164         module.populated.set(true)
1165     }
1166
1167     /// Ensures that the reduced graph rooted at the given external module
1168     /// is built, building it if it is not.
1169     fn populate_module_if_necessary(&mut self, module: &Rc<Module>) {
1170         if !module.populated.get() {
1171             self.populate_external_module(module)
1172         }
1173         assert!(module.populated.get())
1174     }
1175
1176     /// Builds the reduced graph rooted at the 'use' directive for an external
1177     /// crate.
1178     fn build_reduced_graph_for_external_crate(&mut self, root: &Rc<Module>) {
1179         csearch::each_top_level_item_of_crate(&self.session.cstore,
1180                                               root.def_id
1181                                                   .get()
1182                                                   .unwrap()
1183                                                   .krate,
1184                                               |def_like, name, visibility| {
1185             self.build_reduced_graph_for_external_crate_def(root, def_like, name, visibility)
1186         });
1187     }
1188
1189     /// Creates and adds an import directive to the given module.
1190     fn build_import_directive(&mut self,
1191                               module_: &Module,
1192                               module_path: Vec<Name>,
1193                               subclass: ImportDirectiveSubclass,
1194                               span: Span,
1195                               id: NodeId,
1196                               is_public: bool,
1197                               shadowable: Shadowable) {
1198         module_.imports.borrow_mut().push(ImportDirective::new(module_path,
1199                                                                subclass,
1200                                                                span,
1201                                                                id,
1202                                                                is_public,
1203                                                                shadowable));
1204         self.unresolved_imports += 1;
1205         // Bump the reference count on the name. Or, if this is a glob, set
1206         // the appropriate flag.
1207
1208         match subclass {
1209             SingleImport(target, _) => {
1210                 debug!("(building import directive) building import \
1211                         directive: {}::{}",
1212                        self.names_to_string(&module_.imports.borrow().last().unwrap().
1213                                                              module_path[]),
1214                        token::get_name(target));
1215
1216                 let mut import_resolutions = module_.import_resolutions
1217                                                     .borrow_mut();
1218                 match import_resolutions.get_mut(&target) {
1219                     Some(resolution) => {
1220                         debug!("(building import directive) bumping \
1221                                 reference");
1222                         resolution.outstanding_references += 1;
1223
1224                         // the source of this name is different now
1225                         resolution.type_id = id;
1226                         resolution.value_id = id;
1227                         resolution.is_public = is_public;
1228                         return;
1229                     }
1230                     None => {}
1231                 }
1232                 debug!("(building import directive) creating new");
1233                 let mut resolution = ImportResolution::new(id, is_public);
1234                 resolution.outstanding_references = 1;
1235                 import_resolutions.insert(target, resolution);
1236             }
1237             GlobImport => {
1238                 // Set the glob flag. This tells us that we don't know the
1239                 // module's exports ahead of time.
1240
1241                 module_.glob_count.set(module_.glob_count.get() + 1);
1242             }
1243         }
1244     }
1245 }
1246
1247 struct BuildReducedGraphVisitor<'a, 'b:'a, 'tcx:'b> {
1248     builder: GraphBuilder<'a, 'b, 'tcx>,
1249     parent: Rc<Module>
1250 }
1251
1252 impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
1253     fn visit_item(&mut self, item: &Item) {
1254         let p = self.builder.build_reduced_graph_for_item(item, &self.parent);
1255         let old_parent = replace(&mut self.parent, p);
1256         visit::walk_item(self, item);
1257         self.parent = old_parent;
1258     }
1259
1260     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
1261         let parent = &self.parent;
1262         self.builder.build_reduced_graph_for_foreign_item(foreign_item,
1263                                                           parent,
1264                                                           |r| {
1265             let mut v = BuildReducedGraphVisitor {
1266                 builder: GraphBuilder { resolver: r },
1267                 parent: parent.clone()
1268             };
1269             visit::walk_foreign_item(&mut v, foreign_item);
1270         })
1271     }
1272
1273     fn visit_view_item(&mut self, view_item: &ViewItem) {
1274         self.builder.build_reduced_graph_for_view_item(view_item, &self.parent);
1275     }
1276
1277     fn visit_block(&mut self, block: &Block) {
1278         let np = self.builder.build_reduced_graph_for_block(block, &self.parent);
1279         let old_parent = replace(&mut self.parent, np);
1280         visit::walk_block(self, block);
1281         self.parent = old_parent;
1282     }
1283 }
1284
1285 pub fn build_reduced_graph(resolver: &mut Resolver, krate: &ast::Crate) {
1286     GraphBuilder {
1287         resolver: resolver
1288     }.build_reduced_graph(krate);
1289 }
1290
1291 pub fn populate_module_if_necessary(resolver: &mut Resolver, module: &Rc<Module>) {
1292     GraphBuilder {
1293         resolver: resolver
1294     }.populate_module_if_necessary(module);
1295 }