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.
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.
11 //! Reduced graph building
13 //! Here we build the "reduced graph": the graph of the module tree without
14 //! any imports resolved.
16 use {DefModifiers, PUBLIC, IMPORTABLE};
18 use ImportDirectiveSubclass::{self, SingleImport, GlobImport};
22 use Namespace::{TypeNS, ValueNS};
24 use ParentLink::{self, ModuleParentLink, BlockParentLink};
29 use TypeParameters::HasTypeParameters;
31 use self::DuplicateCheckingMode::*;
32 use self::NamespaceError::*;
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;
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;
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};
64 use std::mem::replace;
65 use std::ops::{Deref, DerefMut};
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,
79 #[derive(Copy, PartialEq)]
87 fn namespace_error_to_string(ns: NamespaceError) -> &'static str {
90 ModuleError | TypeError => "type or module",
91 ValueError => "value",
95 struct GraphBuilder<'a, 'b:'a, 'tcx:'b> {
96 resolver: &'a mut Resolver<'b, 'tcx>
99 impl<'a, 'b:'a, 'tcx:'b> Deref for GraphBuilder<'a, 'b, 'tcx> {
100 type Target = Resolver<'b, 'tcx>;
102 fn deref(&self) -> &Resolver<'b, 'tcx> {
107 impl<'a, 'b:'a, 'tcx:'b> DerefMut for GraphBuilder<'a, 'b, 'tcx> {
108 fn deref_mut(&mut self) -> &mut Resolver<'b, 'tcx> {
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 {
121 visit::walk_crate(&mut visitor, krate);
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.
132 /// Panics if this node does not have a module definition and we are not inside
137 duplicate_checking_mode: DuplicateCheckingMode,
138 // For printing errors
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.
145 self.check_for_conflicts_between_external_crates_and_items(&**parent,
149 // Add or reuse the child.
150 let child = parent.children.borrow().get(&name).cloned();
153 let child = Rc::new(NameBindings::new());
154 parent.children.borrow_mut().insert(name, child.clone());
158 // Enforce the duplicate checking mode:
160 // * If we're requesting duplicate module checking, check that
161 // there isn't a module in the module with the same name.
163 // * If we're requesting duplicate type checking, check that
164 // there isn't a type in the module with the same name.
166 // * If we're requesting duplicate value checking, check that
167 // there isn't a value in the module with the same name.
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.
173 // * If no duplicate checking was requested at all, do
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;
184 ForbidDuplicateTypesAndModules => {
185 match child.def_for_namespace(TypeNS) {
187 Some(_) if child.get_module_if_available()
188 .map(|m| m.kind.get()) ==
189 Some(ImplModuleKind) => {}
190 Some(_) => duplicate_type = TypeError
194 ForbidDuplicateValues => {
195 if child.defined_in_namespace(ValueNS) {
196 duplicate_type = ValueError;
200 ForbidDuplicateTypesAndValues => {
202 match child.def_for_namespace(TypeNS) {
203 Some(DefMod(_)) | None => {}
206 duplicate_type = TypeError;
209 if child.defined_in_namespace(ValueNS) {
210 duplicate_type = ValueError;
215 OverwriteDuplicates => None
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))[]);
226 let r = child.span_for_namespace(ns);
228 self.session.span_note(*sp,
229 &format!("first definition of {} `{}` here",
230 namespace_error_to_string(duplicate_type),
231 token::get_name(name))[]);
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 {
246 // Check each statement.
247 for statement in block.stmts.iter() {
248 match statement.node {
249 StmtDecl(ref declaration, _) => {
250 match declaration.node {
265 // If we found neither view items nor items, we don't need to create
266 // an anonymous module.
271 fn get_parent_link(&mut self, parent: &Rc<Module>, name: Name) -> ParentLink {
272 ModuleParentLink(parent.downgrade(), name)
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;
279 let is_public = item.vis == ast::Public;
280 let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
284 let name_bindings = self.add_child(name, parent, ForbidDuplicateModules, sp);
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,
292 item.vis == ast::Public,
295 name_bindings.get_module()
298 ItemForeignMod(..) => parent.clone(),
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;
305 name_bindings.define_value(DefStatic(local_def(item.id), mutbl), sp, modifiers);
309 self.add_child(name, parent, ForbidDuplicateValues, sp)
310 .define_value(DefConst(local_def(item.id)), sp, modifiers);
313 ItemFn(_, _, _, _, _) => {
314 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
316 let def = DefFn(local_def(item.id), false);
317 name_bindings.define_value(def, sp, modifiers);
321 // These items live in the type namespace.
324 self.add_child(name, parent, ForbidDuplicateTypesAndModules,
327 name_bindings.define_type(DefTy(local_def(item.id), false), sp,
330 let parent_link = self.get_parent_link(parent, name);
331 name_bindings.set_module_kind(parent_link,
332 Some(local_def(item.id)),
340 ItemEnum(ref enum_definition, _) => {
342 self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
344 name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers);
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)),
357 let module = name_bindings.get_module();
359 for variant in (*enum_definition).variants.iter() {
360 self.build_reduced_graph_for_variant(
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)
376 let name_bindings = self.add_child(name, parent, forbid, sp);
378 // Define a name in the type namespace.
379 name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers);
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);
387 // Record the def ID and fields of this struct.
388 let named_fields = struct_def.fields.iter().filter_map(|f| {
390 NamedField(ident, _) => Some(ident.name),
391 UnnamedField(_) => None
394 self.structs.insert(local_def(item.id), named_fields);
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.
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)
410 TyObjectSum(ref lhs_ty, _) => {
412 TyPath(ref path, _) if path.segments.len() == 1 => {
413 Some(path.segments.last().unwrap().identifier.name)
425 let mod_name = match mod_name {
426 Some(mod_name) => mod_name,
428 self.resolve_error(ty.span,
429 "inherent implementations may \
430 only be implemented in the same \
431 module as the type they are \
433 return parent.clone();
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 {
441 Some(ref child) if (child.kind.get() == ImplModuleKind ||
442 child.kind.get() == TraitModuleKind) => {
445 Some(ref child) if child.kind.get() == EnumModuleKind ||
446 child.kind.get() == TypeModuleKind => {
452 self.add_child(mod_name, parent, ForbidDuplicateModules, sp);
454 let parent_link = self.get_parent_link(parent, name);
455 let def_id = local_def(item.id);
458 !name_bindings.defined_in_namespace(ns) ||
459 name_bindings.defined_in_public_namespace(ns);
461 name_bindings.define_module(parent_link,
468 name_bindings.get_module()
472 // For each implementation item...
473 for impl_item in impl_items.iter() {
475 MethodImplItem(ref method) => {
476 // Add the method to the module.
477 let name = method.pe_ident().name;
478 let method_name_bindings =
481 ForbidDuplicateValues,
483 let def = match method.pe_explicit_self()
486 // Static methods become
487 // `DefStaticMethod`s.
488 DefStaticMethod(local_def(method.id),
489 FromImpl(local_def(item.id)))
492 // Non-static methods become
494 DefMethod(local_def(method.id),
496 FromImpl(local_def(item.id)))
500 // NB: not IMPORTABLE
501 let modifiers = if method.pe_vis() == ast::Public {
504 DefModifiers::empty()
506 method_name_bindings.define_value(
511 TypeImplItem(ref typedef) => {
512 // Add the typedef to the module.
513 let name = typedef.ident.name;
514 let typedef_name_bindings =
518 ForbidDuplicateTypesAndModules,
520 let def = DefAssociatedTy(local_def(
522 // NB: not IMPORTABLE
523 let modifiers = if typedef.vis == ast::Public {
526 DefModifiers::empty()
528 typedef_name_bindings.define_type(
538 ItemImpl(_, _, _, Some(_), _, _) => parent.clone(),
540 ItemTrait(_, _, _, ref items) => {
542 self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
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)),
550 item.vis == ast::Public,
552 let module_parent = name_bindings.get_module();
554 let def_id = local_def(item.id);
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);
563 let name = ty_m.ident.name;
565 // Add it as a name in the trait module.
566 let (def, static_flag) = match ty_m.explicit_self
569 // Static methods become `DefStaticMethod`s.
572 FromTrait(local_def(item.id))),
573 StaticMethodTraitItemKind)
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)
584 let method_name_bindings =
587 ForbidDuplicateTypesAndValues,
589 // NB: not IMPORTABLE
590 method_name_bindings.define_value(def,
596 ast::TypeTraitItem(ref associated_type) => {
597 let def = DefAssociatedTy(local_def(
598 associated_type.ty_param.id));
601 self.add_child(associated_type.ty_param.ident.name,
603 ForbidDuplicateTypesAndValues,
604 associated_type.ty_param.span);
605 // NB: not IMPORTABLE
606 name_bindings.define_type(def,
607 associated_type.ty_param.span,
610 (associated_type.ty_param.ident.name, TypeTraitItemKind)
614 self.trait_item_map.insert((name, def_id), kind);
617 name_bindings.define_type(DefTrait(def_id), sp, modifiers);
620 ItemMac(..) => parent.clone()
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,
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());
640 let child = self.add_child(name, parent,
641 ForbidDuplicateTypesAndValues,
643 // variants are always treated as importable to allow them to be glob
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);
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, _) => {
665 .iter().map(|ident| ident.identifier.name)
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()
676 // Build up the import directives.
677 let is_public = view_item.vis == ast::Public;
682 attr.name() == token::get_name(
683 special_idents::prelude_import.name)
685 let shadowable = if shadowable {
691 match view_path.node {
692 ViewPathSimple(binding, ref full_path, id) => {
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");
701 let subclass = SingleImport(binding.name,
703 self.build_import_directive(&**parent,
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),
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");
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() {
734 self.resolve_error(source_item.span,
735 "`self` import can only appear in an import list \
736 with a non-empty prefix");
740 let module_path = module_path.init();
741 (module_path.to_vec(), name)
744 self.build_import_directive(
747 SingleImport(name, name),
749 source_item.node.id(),
754 ViewPathGlob(_, id) => {
755 self.build_import_directive(&**parent,
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,
778 debug!("(build reduced graph for item) found extern `{}`",
779 self.module_to_string(&*external_module));
780 self.check_for_conflicts_between_external_crates(
784 parent.external_module_children.borrow_mut()
785 .insert(name.name, external_module.clone());
786 self.build_reduced_graph_for_external_crate(&external_module);
792 /// Constructs the reduced graph for one foreign item.
793 fn build_reduced_graph_for_foreign_item<F>(&mut self,
794 foreign_item: &ForeignItem,
797 F: FnOnce(&mut Resolver),
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;
803 self.add_child(name, parent, ForbidDuplicateValues,
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);
811 self.with_type_parameter_rib(
812 HasTypeParameters(generics,
818 ForeignItemStatic(_, m) => {
819 let def = DefStatic(local_def(foreign_item.id), m);
820 name_bindings.define_value(def, foreign_item.span, modifiers);
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;
831 debug!("(building reduced graph for block) creating a new \
832 anonymous module for block {}",
835 let new_module = Rc::new(Module::new(
836 BlockParentLink(parent.downgrade(), block_id),
841 parent.anonymous_children.borrow_mut().insert(block_id, new_module.clone());
848 fn handle_external_def(&mut self,
851 child_name_bindings: &NameBindings,
854 new_parent: &Rc<Module>) {
855 debug!("(building reduced graph for \
856 external crate) building external def, priv {:?}",
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() {
862 Some(did) => self.external_exports.contains(&did)
865 self.external_exports.insert(def.def_id());
868 let kind = match def {
869 DefTy(_, true) => EnumModuleKind,
870 DefTy(_, false) => TypeModuleKind,
871 DefStruct(..) => ImplModuleKind,
872 _ => NormalModuleKind
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();
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));
886 debug!("(building reduced graph for \
887 external crate) building module \
889 let parent_link = self.get_parent_link(new_parent, name);
891 child_name_bindings.define_module(parent_link,
904 DefMod(_) | DefForeignMod(_) => {}
905 DefVariant(_, variant_id, is_struct) => {
906 debug!("(building reduced graph for external crate) building \
909 // variants are always treated as importable to allow them to be
911 let modifiers = PUBLIC | IMPORTABLE;
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());
917 child_name_bindings.define_value(def, DUMMY_SP, modifiers);
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);
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),
933 if new_parent.kind.get() != NormalModuleKind {
934 modifiers = modifiers & !IMPORTABLE;
936 child_name_bindings.define_value(def, DUMMY_SP, modifiers);
938 DefTrait(def_id) => {
939 debug!("(building reduced graph for external \
940 crate) building type {}", final_ident);
942 // If this is a trait, add all the trait item names to the trait
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());
953 debug!("(building reduced graph for external crate) ... \
954 adding trait item '{}'",
955 token::get_name(trait_item_name));
957 self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind);
960 self.external_exports
961 .insert(trait_item_def_id.def_id());
965 child_name_bindings.define_type(def, DUMMY_SP, modifiers);
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,
976 DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => {
977 debug!("(building reduced graph for external \
978 crate) building type {}", final_ident);
980 child_name_bindings.define_type(def, DUMMY_SP, modifiers);
982 DefStruct(def_id) => {
983 debug!("(building reduced graph for external \
984 crate) building type and value for {}",
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| {
989 }).collect::<Vec<_>>();
991 if fields.len() == 0 {
992 child_name_bindings.define_value(def, DUMMY_SP, modifiers);
995 // Record the def ID and fields of this struct.
996 self.structs.insert(def_id, fields);
998 DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
999 DefUse(..) | DefUpvar(..) | DefRegion(..) |
1000 DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
1001 panic!("didn't expect `{:?}`", def);
1006 /// Builds the reduced graph for a single item in an external crate.
1007 fn build_reduced_graph_for_external_crate_def(&mut self,
1011 def_visibility: Visibility) {
1014 // Add the new child item, if necessary.
1016 DefForeignMod(def_id) => {
1017 // Foreign modules have no names. Recur and populate
1019 csearch::each_child_of_item(&self.session.cstore,
1024 self.build_reduced_graph_for_external_crate_def(
1032 let child_name_bindings =
1033 self.add_child(name,
1035 OverwriteDuplicates,
1038 self.handle_external_def(def,
1040 &*child_name_bindings,
1041 token::get_name(name).get(),
1048 match csearch::get_type_name_if_impl(&self.session.cstore, def) {
1050 Some(final_name) => {
1052 csearch::get_methods_if_impl(&self.session.cstore, def);
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));
1061 let child_name_bindings =
1065 OverwriteDuplicates,
1068 // Process the static methods. First,
1069 // create the module.
1071 let type_def = child_name_bindings.type_def.borrow().clone();
1074 module_def: Some(module_def),
1077 // We already have a module. This
1079 type_module = module_def;
1081 // Mark it as an impl module if
1083 type_module.kind.set(ImplModuleKind);
1087 self.get_parent_link(root, final_name);
1088 child_name_bindings.define_module(
1096 child_name_bindings.
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));
1110 let method_name_bindings =
1111 self.add_child(name,
1113 OverwriteDuplicates,
1115 let def = DefFn(method_info.def_id, false);
1117 // NB: not IMPORTABLE
1118 let modifiers = if method_info.vis == ast::Public {
1121 DefModifiers::empty()
1123 method_name_bindings.define_value(
1124 def, DUMMY_SP, modifiers);
1128 // Otherwise, do nothing.
1129 Some(_) | None => {}
1135 debug!("(building reduced graph for external crate) \
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));
1146 let def_id = match module.def_id.get() {
1148 debug!("(populating external module) ... no def ID!");
1151 Some(def_id) => def_id,
1154 csearch::each_child_of_item(&self.session.cstore,
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,
1164 module.populated.set(true)
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)
1173 assert!(module.populated.get())
1176 /// Builds the reduced graph rooted at the 'use' directive for an external
1178 fn build_reduced_graph_for_external_crate(&mut self, root: &Rc<Module>) {
1179 csearch::each_top_level_item_of_crate(&self.session.cstore,
1184 |def_like, name, visibility| {
1185 self.build_reduced_graph_for_external_crate_def(root, def_like, name, visibility)
1189 /// Creates and adds an import directive to the given module.
1190 fn build_import_directive(&mut self,
1192 module_path: Vec<Name>,
1193 subclass: ImportDirectiveSubclass,
1197 shadowable: Shadowable) {
1198 module_.imports.borrow_mut().push(ImportDirective::new(module_path,
1204 self.unresolved_imports += 1;
1205 // Bump the reference count on the name. Or, if this is a glob, set
1206 // the appropriate flag.
1209 SingleImport(target, _) => {
1210 debug!("(building import directive) building import \
1212 self.names_to_string(&module_.imports.borrow().last().unwrap().
1214 token::get_name(target));
1216 let mut import_resolutions = module_.import_resolutions
1218 match import_resolutions.get_mut(&target) {
1219 Some(resolution) => {
1220 debug!("(building import directive) bumping \
1222 resolution.outstanding_references += 1;
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;
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);
1238 // Set the glob flag. This tells us that we don't know the
1239 // module's exports ahead of time.
1241 module_.glob_count.set(module_.glob_count.get() + 1);
1247 struct BuildReducedGraphVisitor<'a, 'b:'a, 'tcx:'b> {
1248 builder: GraphBuilder<'a, 'b, 'tcx>,
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;
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,
1265 let mut v = BuildReducedGraphVisitor {
1266 builder: GraphBuilder { resolver: r },
1267 parent: parent.clone()
1269 visit::walk_foreign_item(&mut v, foreign_item);
1273 fn visit_view_item(&mut self, view_item: &ViewItem) {
1274 self.builder.build_reduced_graph_for_view_item(view_item, &self.parent);
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;
1285 pub fn build_reduced_graph(resolver: &mut Resolver, krate: &ast::Crate) {
1288 }.build_reduced_graph(krate);
1291 pub fn populate_module_if_necessary(resolver: &mut Resolver, module: &Rc<Module>) {
1294 }.populate_module_if_necessary(module);