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