//! any imports resolved.
use DefModifiers;
-use resolve_imports::ImportDirective;
-use resolve_imports::ImportDirectiveSubclass::{self, SingleImport, GlobImport};
+use resolve_imports::ImportDirectiveSubclass::{self, GlobImport};
use Module;
use Namespace::{self, TypeNS, ValueNS};
use {NameBinding, NameBindingKind};
-use module_to_string;
use ParentLink::{ModuleParentLink, BlockParentLink};
use Resolver;
-use resolve_imports::Shadowable;
use {resolve_error, resolve_struct_error, ResolutionError};
-use rustc::middle::cstore::{CrateStore, ChildItem, DlDef, DlField, DlImpl};
-use rustc::middle::def::*;
-use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId};
-use rustc::middle::ty::VariantKind;
+use rustc::middle::cstore::{CrateStore, ChildItem, DlDef};
+use rustc::lint;
+use rustc::hir::def::*;
+use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
+use rustc::ty::{self, VariantKind};
-use syntax::ast::{Name, NodeId};
+use syntax::ast::Name;
use syntax::attr::AttrMetaMethods;
-use syntax::parse::token::special_idents;
+use syntax::parse::token::{special_idents, SELF_KEYWORD_NAME, SUPER_KEYWORD_NAME};
use syntax::codemap::{Span, DUMMY_SP};
-use rustc_front::hir;
-use rustc_front::hir::{Block, DeclItem};
-use rustc_front::hir::{ForeignItem, ForeignItemFn, ForeignItemStatic};
-use rustc_front::hir::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
-use rustc_front::hir::{ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
-use rustc_front::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
-use rustc_front::hir::{NamedField, PathListIdent, PathListMod};
-use rustc_front::hir::StmtDecl;
-use rustc_front::hir::UnnamedField;
-use rustc_front::hir::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
-use rustc_front::hir::Visibility;
-use rustc_front::intravisit::{self, Visitor};
-
-use std::mem::replace;
-use std::ops::{Deref, DerefMut};
-
-struct GraphBuilder<'a, 'b: 'a, 'tcx: 'b> {
- resolver: &'a mut Resolver<'b, 'tcx>,
-}
-
-impl<'a, 'b:'a, 'tcx:'b> Deref for GraphBuilder<'a, 'b, 'tcx> {
- type Target = Resolver<'b, 'tcx>;
-
- fn deref(&self) -> &Resolver<'b, 'tcx> {
- &*self.resolver
- }
-}
-
-impl<'a, 'b:'a, 'tcx:'b> DerefMut for GraphBuilder<'a, 'b, 'tcx> {
- fn deref_mut(&mut self) -> &mut Resolver<'b, 'tcx> {
- &mut *self.resolver
- }
-}
+use rustc::hir;
+use rustc::hir::{Block, DeclItem};
+use rustc::hir::{ForeignItem, ForeignItemFn, ForeignItemStatic};
+use rustc::hir::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
+use rustc::hir::{ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
+use rustc::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
+use rustc::hir::{PathListIdent, PathListMod, StmtDecl};
+use rustc::hir::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
+use rustc::hir::intravisit::{self, Visitor};
trait ToNameBinding<'a> {
fn to_name_binding(self) -> NameBinding<'a>;
}
}
-impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
+impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
/// Constructs the reduced graph for the entire crate.
- fn build_reduced_graph(self, krate: &hir::Crate) {
+ pub fn build_reduced_graph(&mut self, krate: &hir::Crate) {
let mut visitor = BuildReducedGraphVisitor {
parent: self.graph_root,
- builder: self,
+ resolver: self,
};
intravisit::walk_crate(&mut visitor, krate);
}
fn try_define<T>(&self, parent: Module<'b>, name: Name, ns: Namespace, def: T)
where T: ToNameBinding<'b>
{
- let _ = parent.try_define_child(name, ns, self.new_name_binding(def.to_name_binding()));
+ let _ = parent.try_define_child(name, ns, def.to_name_binding());
}
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
/// otherwise, reports an error.
fn define<T: ToNameBinding<'b>>(&self, parent: Module<'b>, name: Name, ns: Namespace, def: T) {
- let binding = self.new_name_binding(def.to_name_binding());
- let old_binding = match parent.try_define_child(name, ns, binding) {
- Ok(()) => return,
- Err(old_binding) => old_binding,
- };
-
- let span = binding.span.unwrap_or(DUMMY_SP);
- if !old_binding.is_extern_crate() && !binding.is_extern_crate() {
- // Record an error here by looking up the namespace that had the duplicate
- let ns_str = match ns { TypeNS => "type or module", ValueNS => "value" };
- let resolution_error = ResolutionError::DuplicateDefinition(ns_str, name);
- let mut err = resolve_struct_error(self, span, resolution_error);
-
- if let Some(sp) = old_binding.span {
- let note = format!("first definition of {} `{}` here", ns_str, name);
- err.span_note(sp, ¬e);
- }
- err.emit();
- } else if old_binding.is_extern_crate() && binding.is_extern_crate() {
- span_err!(self.session,
- span,
- E0259,
- "an external crate named `{}` has already been imported into this module",
- name);
- } else {
- span_err!(self.session,
- span,
- E0260,
- "the name `{}` conflicts with an external crate \
- that has been imported into this module",
- name);
+ let binding = def.to_name_binding();
+ if let Err(old_binding) = parent.try_define_child(name, ns, binding.clone()) {
+ self.report_conflict(parent, name, ns, old_binding, &binding);
}
}
}
/// Constructs the reduced graph for one item.
- fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> Module<'b> {
+ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<'b>) {
+ let parent = *parent_ref;
let name = item.name;
let sp = item.span;
let is_public = item.vis == hir::Public;
// Extract and intern the module part of the path. For
// globs and lists, the path is found directly in the AST;
// for simple paths we have to munge the path a little.
- let module_path = match view_path.node {
+ let is_global;
+ let module_path: Vec<Name> = match view_path.node {
ViewPathSimple(_, ref full_path) => {
+ is_global = full_path.global;
full_path.segments
.split_last()
.unwrap()
ViewPathGlob(ref module_ident_path) |
ViewPathList(ref module_ident_path, _) => {
+ is_global = module_ident_path.global;
module_ident_path.segments
.iter()
.map(|seg| seg.identifier.name)
}
};
+ // Checking for special identifiers in path
+ // prevent `self` or `super` at beginning of global path
+ if is_global && (module_path.first() == Some(&SELF_KEYWORD_NAME) ||
+ module_path.first() == Some(&SUPER_KEYWORD_NAME)) {
+ self.session.add_lint(
+ lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH,
+ item.id,
+ item.span,
+ format!("expected identifier, found keyword `{}`",
+ module_path.first().unwrap().as_str()));
+ }
+
// Build up the import directives.
- let shadowable = item.attrs.iter().any(|attr| {
+ let is_prelude = item.attrs.iter().any(|attr| {
attr.name() == special_idents::prelude_import.name.as_str()
});
- let shadowable = if shadowable {
- Shadowable::Always
- } else {
- Shadowable::Never
- };
match view_path.node {
ViewPathSimple(binding, ref full_path) => {
ResolutionError::SelfImportsOnlyAllowedWithin);
}
- let subclass = SingleImport(binding, source_name);
- self.build_import_directive(parent,
- module_path,
+ let subclass = ImportDirectiveSubclass::single(binding, source_name);
+ self.unresolved_imports += 1;
+ parent.add_import_directive(module_path,
subclass,
view_path.span,
item.id,
is_public,
- shadowable);
+ is_prelude);
}
ViewPathList(_, ref source_items) => {
// Make sure there's at most one `mod` import in the list.
(module_path.to_vec(), name, rename)
}
};
- self.build_import_directive(parent,
- module_path,
- SingleImport(rename, name),
+ let subclass = ImportDirectiveSubclass::single(rename, name);
+ self.unresolved_imports += 1;
+ parent.add_import_directive(module_path,
+ subclass,
source_item.span,
source_item.node.id(),
is_public,
- shadowable);
+ is_prelude);
}
}
ViewPathGlob(_) => {
- self.build_import_directive(parent,
- module_path,
+ self.unresolved_imports += 1;
+ parent.add_import_directive(module_path,
GlobImport,
view_path.span,
item.id,
is_public,
- shadowable);
+ is_prelude);
}
}
- parent
}
ItemExternCrate(_) => {
krate: crate_id,
index: CRATE_DEF_INDEX,
};
- self.external_exports.insert(def_id);
let parent_link = ModuleParentLink(parent, name);
let def = Def::Mod(def_id);
- let local_def_id = self.ast_map.local_def_id(item.id);
- let external_module =
- self.new_extern_crate_module(parent_link, def, is_public, local_def_id);
- self.define(parent, name, TypeNS, (external_module, sp));
-
- if is_public {
- let export = Export { name: name, def_id: def_id };
- if let Some(def_id) = parent.def_id() {
- let node_id = self.resolver.ast_map.as_local_node_id(def_id).unwrap();
- self.export_map.entry(node_id).or_insert(Vec::new()).push(export);
- }
- }
+ let module = self.new_extern_crate_module(parent_link, def, is_public, item.id);
+ self.define(parent, name, TypeNS, (module, sp));
- self.build_reduced_graph_for_external_crate(external_module);
+ self.build_reduced_graph_for_external_crate(module);
}
- parent
}
ItemMod(..) => {
let module = self.new_module(parent_link, Some(def), false, is_public);
self.define(parent, name, TypeNS, (module, sp));
parent.module_children.borrow_mut().insert(item.id, module);
- module
+ *parent_ref = module;
}
- ItemForeignMod(..) => parent,
+ ItemForeignMod(..) => {}
// These items live in the value namespace.
ItemStatic(_, m, _) => {
let mutbl = m == hir::MutMutable;
let def = Def::Static(self.ast_map.local_def_id(item.id), mutbl);
self.define(parent, name, ValueNS, (def, sp, modifiers));
- parent
}
ItemConst(_, _) => {
let def = Def::Const(self.ast_map.local_def_id(item.id));
self.define(parent, name, ValueNS, (def, sp, modifiers));
- parent
}
ItemFn(_, _, _, _, _, _) => {
let def = Def::Fn(self.ast_map.local_def_id(item.id));
self.define(parent, name, ValueNS, (def, sp, modifiers));
- parent
}
// These items live in the type namespace.
ItemTy(..) => {
- let parent_link = ModuleParentLink(parent, name);
let def = Def::TyAlias(self.ast_map.local_def_id(item.id));
- let module = self.new_module(parent_link, Some(def), false, is_public);
- self.define(parent, name, TypeNS, (module, sp));
- parent
+ self.define(parent, name, TypeNS, (def, sp, modifiers));
}
ItemEnum(ref enum_definition, _) => {
self.build_reduced_graph_for_variant(variant, item_def_id,
module, variant_modifiers);
}
- parent
}
// These items live in both the type and value namespaces.
}
// Record the def ID and fields of this struct.
- let named_fields = struct_def.fields()
- .iter()
- .filter_map(|f| {
- match f.node.kind {
- NamedField(name, _) => Some(name),
- UnnamedField(_) => None,
- }
- })
- .collect();
+ let field_names = struct_def.fields()
+ .iter()
+ .map(|f| f.name)
+ .collect();
let item_def_id = self.ast_map.local_def_id(item.id);
- self.structs.insert(item_def_id, named_fields);
-
- parent
+ self.structs.insert(item_def_id, field_names);
}
- ItemDefaultImpl(_, _) |
- ItemImpl(..) => parent,
+ ItemDefaultImpl(_, _) | ItemImpl(..) => {}
ItemTrait(_, _, _, ref items) => {
let def_id = self.ast_map.local_def_id(item.id);
self.trait_item_map.insert((item.name, def_id), item_def_id);
}
-
- parent
}
}
}
self.define(parent, name, ValueNS, (def, foreign_item.span, modifiers));
}
- fn build_reduced_graph_for_block(&mut self, block: &Block, parent: Module<'b>) -> Module<'b> {
+ fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &mut Module<'b>) {
if self.block_needs_anonymous_module(block) {
let block_id = block.id;
let parent_link = BlockParentLink(parent, block_id);
let new_module = self.new_module(parent_link, None, false, false);
parent.module_children.borrow_mut().insert(block_id, new_module);
- new_module
- } else {
- parent
+ *parent = new_module;
}
}
- fn handle_external_def(&mut self,
- def: Def,
- vis: Visibility,
- final_ident: &str,
- name: Name,
- new_parent: Module<'b>) {
- debug!("(building reduced graph for external crate) building external def {}, priv {:?}",
- final_ident,
- vis);
- let is_public = vis == hir::Public;
+ /// Builds the reduced graph for a single item in an external crate.
+ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, xcdef: ChildItem) {
+ let def = match xcdef.def {
+ DlDef(def) => def,
+ _ => return,
+ };
+
+ if let Def::ForeignMod(def_id) = def {
+ // Foreign modules have no names. Recur and populate eagerly.
+ for child in self.session.cstore.item_children(def_id) {
+ self.build_reduced_graph_for_external_crate_def(parent, child);
+ }
+ return;
+ }
+
+ let name = xcdef.name;
+ let is_public = xcdef.vis == ty::Visibility::Public || parent.is_trait();
let mut modifiers = DefModifiers::empty();
if is_public {
modifiers = modifiers | DefModifiers::PUBLIC;
}
- if new_parent.is_normal() {
+ if parent.is_normal() {
modifiers = modifiers | DefModifiers::IMPORTABLE;
}
- let is_exported = is_public &&
- match new_parent.def_id() {
- None => true,
- Some(did) => self.external_exports.contains(&did),
- };
- if is_exported {
- self.external_exports.insert(def.def_id());
- }
-
match def {
- Def::Mod(_) | Def::ForeignMod(_) | Def::Enum(..) | Def::TyAlias(..) => {
+ Def::Mod(_) | Def::ForeignMod(_) | Def::Enum(..) => {
debug!("(building reduced graph for external crate) building module {} {}",
- final_ident,
+ name,
is_public);
- let parent_link = ModuleParentLink(new_parent, name);
+ let parent_link = ModuleParentLink(parent, name);
let module = self.new_module(parent_link, Some(def), true, is_public);
- self.try_define(new_parent, name, TypeNS, (module, DUMMY_SP));
+ self.try_define(parent, name, TypeNS, (module, DUMMY_SP));
}
Def::Variant(_, variant_id) => {
- debug!("(building reduced graph for external crate) building variant {}",
- final_ident);
+ debug!("(building reduced graph for external crate) building variant {}", name);
// Variants are always treated as importable to allow them to be glob used.
// All variants are defined in both type and value namespaces as future-proofing.
let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE;
- self.try_define(new_parent, name, TypeNS, (def, DUMMY_SP, modifiers));
- self.try_define(new_parent, name, ValueNS, (def, DUMMY_SP, modifiers));
+ self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers));
+ self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers));
if self.session.cstore.variant_kind(variant_id) == Some(VariantKind::Struct) {
// Not adding fields for variants as they are not accessed with a self receiver
self.structs.insert(variant_id, Vec::new());
Def::AssociatedConst(..) |
Def::Method(..) => {
debug!("(building reduced graph for external crate) building value (fn/static) {}",
- final_ident);
- self.try_define(new_parent, name, ValueNS, (def, DUMMY_SP, modifiers));
+ name);
+ self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers));
}
Def::Trait(def_id) => {
- debug!("(building reduced graph for external crate) building type {}",
- final_ident);
+ debug!("(building reduced graph for external crate) building type {}", name);
// If this is a trait, add all the trait item names to the trait
// info.
trait_item_name);
self.trait_item_map.insert((trait_item_name, def_id), trait_item_def.def_id());
-
- if is_exported {
- self.external_exports.insert(trait_item_def.def_id());
- }
}
- let parent_link = ModuleParentLink(new_parent, name);
+ let parent_link = ModuleParentLink(parent, name);
let module = self.new_module(parent_link, Some(def), true, is_public);
- self.try_define(new_parent, name, TypeNS, (module, DUMMY_SP));
+ self.try_define(parent, name, TypeNS, (module, DUMMY_SP));
}
- Def::AssociatedTy(..) => {
- debug!("(building reduced graph for external crate) building type {}",
- final_ident);
- self.try_define(new_parent, name, TypeNS, (def, DUMMY_SP, modifiers));
+ Def::TyAlias(..) | Def::AssociatedTy(..) => {
+ debug!("(building reduced graph for external crate) building type {}", name);
+ self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers));
}
Def::Struct(def_id)
if self.session.cstore.tuple_struct_definition_if_ctor(def_id).is_none() => {
- debug!("(building reduced graph for external crate) building type and value for \
- {}",
- final_ident);
- self.try_define(new_parent, name, TypeNS, (def, DUMMY_SP, modifiers));
+ debug!("(building reduced graph for external crate) building type and value for {}",
+ name);
+ self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers));
if let Some(ctor_def_id) = self.session.cstore.struct_ctor_def_id(def_id) {
let def = Def::Struct(ctor_def_id);
- self.try_define(new_parent, name, ValueNS, (def, DUMMY_SP, modifiers));
+ self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers));
}
// Record the def ID and fields of this struct.
Def::Label(..) |
Def::SelfTy(..) |
Def::Err => {
- panic!("didn't expect `{:?}`", def);
+ bug!("didn't expect `{:?}`", def);
}
}
}
- /// Builds the reduced graph for a single item in an external crate.
- fn build_reduced_graph_for_external_crate_def(&mut self,
- root: Module<'b>,
- xcdef: ChildItem) {
- match xcdef.def {
- DlDef(def) => {
- // Add the new child item, if necessary.
- match def {
- Def::ForeignMod(def_id) => {
- // Foreign modules have no names. Recur and populate
- // eagerly.
- for child in self.session.cstore.item_children(def_id) {
- self.build_reduced_graph_for_external_crate_def(root, child)
- }
- }
- _ => {
- self.handle_external_def(def,
- xcdef.vis,
- &xcdef.name.as_str(),
- xcdef.name,
- root);
- }
- }
- }
- DlImpl(_) => {
- debug!("(building reduced graph for external crate) ignoring impl");
- }
- DlField => {
- debug!("(building reduced graph for external crate) ignoring field");
- }
- }
- }
-
- /// Builds the reduced graph rooted at the given external module.
- fn populate_external_module(&mut self, module: Module<'b>) {
- debug!("(populating external module) attempting to populate {}",
- module_to_string(module));
-
- let def_id = match module.def_id() {
- None => {
- debug!("(populating external module) ... no def ID!");
- return;
- }
- Some(def_id) => def_id,
- };
-
- for child in self.session.cstore.item_children(def_id) {
- debug!("(populating external module) ... found ident: {}",
- child.name);
- self.build_reduced_graph_for_external_crate_def(module, child);
- }
- module.populated.set(true)
- }
-
- /// Ensures that the reduced graph rooted at the given external module
- /// is built, building it if it is not.
- fn populate_module_if_necessary(&mut self, module: Module<'b>) {
- if !module.populated.get() {
- self.populate_external_module(module)
- }
- assert!(module.populated.get())
- }
-
/// Builds the reduced graph rooted at the 'use' directive for an external
/// crate.
fn build_reduced_graph_for_external_crate(&mut self, root: Module<'b>) {
}
}
- /// Creates and adds an import directive to the given module.
- fn build_import_directive(&mut self,
- module_: Module<'b>,
- module_path: Vec<Name>,
- subclass: ImportDirectiveSubclass,
- span: Span,
- id: NodeId,
- is_public: bool,
- shadowable: Shadowable) {
- module_.unresolved_imports
- .borrow_mut()
- .push(ImportDirective::new(module_path, subclass, span, id, is_public, shadowable));
- self.unresolved_imports += 1;
-
- if is_public {
- module_.inc_pub_count();
- }
-
- // Bump the reference count on the name. Or, if this is a glob, set
- // the appropriate flag.
-
- match subclass {
- SingleImport(target, _) => {
- module_.increment_outstanding_references_for(target, ValueNS);
- module_.increment_outstanding_references_for(target, TypeNS);
- }
- GlobImport => {
- // Set the glob flag. This tells us that we don't know the
- // module's exports ahead of time.
-
- module_.inc_glob_count();
- if is_public {
- module_.inc_pub_glob_count();
- }
- }
+ /// Ensures that the reduced graph rooted at the given external module
+ /// is built, building it if it is not.
+ pub fn populate_module_if_necessary(&mut self, module: Module<'b>) {
+ if module.populated.get() { return }
+ for child in self.session.cstore.item_children(module.def_id().unwrap()) {
+ self.build_reduced_graph_for_external_crate_def(module, child);
}
+ module.populated.set(true)
}
}
struct BuildReducedGraphVisitor<'a, 'b: 'a, 'tcx: 'b> {
- builder: GraphBuilder<'a, 'b, 'tcx>,
+ resolver: &'a mut Resolver<'b, 'tcx>,
parent: Module<'b>,
}
impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
fn visit_nested_item(&mut self, item: hir::ItemId) {
- self.visit_item(self.builder.resolver.ast_map.expect_item(item.id))
+ self.visit_item(self.resolver.ast_map.expect_item(item.id))
}
fn visit_item(&mut self, item: &Item) {
- let p = self.builder.build_reduced_graph_for_item(item, &self.parent);
- let old_parent = replace(&mut self.parent, p);
+ let old_parent = self.parent;
+ self.resolver.build_reduced_graph_for_item(item, &mut self.parent);
intravisit::walk_item(self, item);
self.parent = old_parent;
}
fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
- self.builder.build_reduced_graph_for_foreign_item(foreign_item, &self.parent);
+ self.resolver.build_reduced_graph_for_foreign_item(foreign_item, &self.parent);
}
fn visit_block(&mut self, block: &Block) {
- let np = self.builder.build_reduced_graph_for_block(block, &self.parent);
- let old_parent = replace(&mut self.parent, np);
+ let old_parent = self.parent;
+ self.resolver.build_reduced_graph_for_block(block, &mut self.parent);
intravisit::walk_block(self, block);
self.parent = old_parent;
}
}
-
-pub fn build_reduced_graph(resolver: &mut Resolver, krate: &hir::Crate) {
- GraphBuilder { resolver: resolver }.build_reduced_graph(krate);
-}
-
-pub fn populate_module_if_necessary<'a, 'tcx>(resolver: &mut Resolver<'a, 'tcx>,
- module: Module<'a>) {
- GraphBuilder { resolver: resolver }.populate_module_if_necessary(module);
-}