diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 7f6a587fade..d7fccf03aec 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015-2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -13,10 +13,10 @@ use super::MapEntry::*; use hir::*; use hir::intravisit::Visitor; -use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; +use hir::def_id::DefId; use middle::cstore::InlinedItem; use std::iter::repeat; -use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID}; +use syntax::ast::{NodeId, CRATE_NODE_ID}; use syntax::codemap::Span; /// A Visitor that walks over the HIR and collects Node's into a HIR map. @@ -26,248 +26,6 @@ pub struct NodeCollector<'ast> { pub parent_node: NodeId, } -pub struct DefCollector<'ast> { - pub krate: &'ast Crate, - pub map: &'ast [MapEntry<'ast>], - pub definitions: Definitions, - pub parent_def: Option, -} - -impl<'ast> DefCollector<'ast> { - pub fn root(krate: &'ast Crate, map: &'ast [MapEntry<'ast>]) -> DefCollector<'ast> { - let mut collector = DefCollector { - krate: krate, - map: map, - definitions: Definitions::new(), - parent_def: None, - }; - let result = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot); - assert_eq!(result, CRATE_DEF_INDEX); - - collector.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc); - - collector - } - - pub fn extend(krate: &'ast Crate, - parent_node: NodeId, - parent_def_path: DefPath, - parent_def_id: DefId, - map: &'ast [MapEntry<'ast>], - definitions: Definitions) - -> DefCollector<'ast> { - let mut collector = DefCollector { - krate: krate, - map: map, - parent_def: None, - definitions: definitions, - }; - - assert_eq!(parent_def_path.krate, parent_def_id.krate); - let root_path = Box::new(InlinedRootPath { - data: parent_def_path.data, - def_id: parent_def_id, - }); - - let def = collector.create_def(parent_node, DefPathData::InlinedRoot(root_path)); - collector.parent_def = Some(def); - - collector - } - - fn parent_def(&self) -> Option { - self.parent_def - } - - fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex { - let parent_def = self.parent_def(); - debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); - self.definitions.create_def_with_parent(parent_def, node_id, data) - } - - fn create_def_with_parent(&mut self, - parent: Option, - node_id: NodeId, - data: DefPathData) - -> DefIndex { - self.definitions.create_def_with_parent(parent, node_id, data) - } -} - -impl<'ast> Visitor<'ast> for DefCollector<'ast> { - /// Because we want to track parent items and so forth, enable - /// deep walking so that we walk nested items in the context of - /// their outer items. - fn visit_nested_item(&mut self, item: ItemId) { - debug!("visit_nested_item: {:?}", item); - self.visit_item(self.krate.item(item.id)) - } - - fn visit_item(&mut self, i: &'ast Item) { - debug!("visit_item: {:?}", i); - - // Pick the def data. This need not be unique, but the more - // information we encapsulate into - let def_data = match i.node { - ItemDefaultImpl(..) | ItemImpl(..) => - DefPathData::Impl, - ItemEnum(..) | ItemStruct(..) | ItemTrait(..) | - ItemExternCrate(..) | ItemForeignMod(..) | ItemTy(..) => - DefPathData::TypeNs(i.name), - ItemMod(..) => - DefPathData::Module(i.name), - ItemStatic(..) | ItemConst(..) | ItemFn(..) => - DefPathData::ValueNs(i.name), - ItemUse(..) => - DefPathData::Misc, - }; - - let def = self.create_def(i.id, def_data); - - let parent_def = self.parent_def; - self.parent_def = Some(def); - - match i.node { - ItemEnum(ref enum_definition, _) => { - for v in &enum_definition.variants { - let variant_def_index = - self.create_def(v.node.data.id(), - DefPathData::EnumVariant(v.node.name)); - - for field in v.node.data.fields() { - self.create_def_with_parent( - Some(variant_def_index), - field.id, - DefPathData::Field(field.name)); - } - } - } - ItemStruct(ref struct_def, _) => { - // If this is a tuple-like struct, register the constructor. - if !struct_def.is_struct() { - self.create_def(struct_def.id(), - DefPathData::StructCtor); - } - - for field in struct_def.fields() { - self.create_def(field.id, DefPathData::Field(field.name)); - } - } - _ => {} - } - intravisit::walk_item(self, i); - self.parent_def = parent_def; - } - - fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { - let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.name)); - - let parent_def = self.parent_def; - self.parent_def = Some(def); - intravisit::walk_foreign_item(self, foreign_item); - self.parent_def = parent_def; - } - - fn visit_generics(&mut self, generics: &'ast Generics) { - for ty_param in generics.ty_params.iter() { - self.create_def(ty_param.id, - DefPathData::TypeParam(ty_param.name)); - } - - intravisit::walk_generics(self, generics); - } - - fn visit_trait_item(&mut self, ti: &'ast TraitItem) { - let def_data = match ti.node { - MethodTraitItem(..) | ConstTraitItem(..) => DefPathData::ValueNs(ti.name), - TypeTraitItem(..) => DefPathData::TypeNs(ti.name), - }; - - let def = self.create_def(ti.id, def_data); - - let parent_def = self.parent_def; - self.parent_def = Some(def); - - match ti.node { - ConstTraitItem(_, Some(ref expr)) => { - self.create_def(expr.id, DefPathData::Initializer); - } - _ => { } - } - - intravisit::walk_trait_item(self, ti); - - self.parent_def = parent_def; - } - - fn visit_impl_item(&mut self, ii: &'ast ImplItem) { - let def_data = match ii.node { - ImplItemKind::Method(..) | ImplItemKind::Const(..) => DefPathData::ValueNs(ii.name), - ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name), - }; - - let def = self.create_def(ii.id, def_data); - - let parent_def = self.parent_def; - self.parent_def = Some(def); - - match ii.node { - ImplItemKind::Const(_, ref expr) => { - self.create_def(expr.id, DefPathData::Initializer); - } - _ => { } - } - - intravisit::walk_impl_item(self, ii); - - self.parent_def = parent_def; - } - - fn visit_pat(&mut self, pat: &'ast Pat) { - let maybe_binding = match pat.node { - PatKind::Ident(_, id, _) => Some(id.node), - _ => None - }; - - let parent_def = self.parent_def; - if let Some(id) = maybe_binding { - let def = self.create_def(pat.id, DefPathData::Binding(id.name)); - self.parent_def = Some(def); - } - - intravisit::walk_pat(self, pat); - self.parent_def = parent_def; - } - - fn visit_expr(&mut self, expr: &'ast Expr) { - let parent_def = self.parent_def; - - if let ExprClosure(..) = expr.node { - let def = self.create_def(expr.id, DefPathData::ClosureExpr); - self.parent_def = Some(def); - } - - intravisit::walk_expr(self, expr); - self.parent_def = parent_def; - } - - fn visit_stmt(&mut self, stmt: &'ast Stmt) { - intravisit::walk_stmt(self, stmt); - } - - fn visit_block(&mut self, block: &'ast Block) { - intravisit::walk_block(self, block); - } - - fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) { - self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name)); - } - - fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) { - self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name)); - } -} - impl<'ast> NodeCollector<'ast> { pub fn root(krate: &'ast Crate) -> NodeCollector<'ast> { let mut collector = NodeCollector { diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs new file mode 100644 index 00000000000..0e64a2d676e --- /dev/null +++ b/src/librustc/hir/map/def_collector.rs @@ -0,0 +1,258 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use super::*; + +use hir::*; +use hir::intravisit::Visitor; +use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; +use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID}; + +/// Creates def ids for nodes in the HIR. +pub struct DefCollector<'ast> { + pub krate: &'ast Crate, + pub map: &'ast [MapEntry<'ast>], + pub definitions: Definitions, + pub parent_def: Option, +} + +impl<'ast> DefCollector<'ast> { + pub fn root(krate: &'ast Crate, map: &'ast [MapEntry<'ast>]) -> DefCollector<'ast> { + let mut collector = DefCollector { + krate: krate, + map: map, + definitions: Definitions::new(), + parent_def: None, + }; + let result = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot); + assert_eq!(result, CRATE_DEF_INDEX); + + collector.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc); + + collector + } + + pub fn extend(krate: &'ast Crate, + parent_node: NodeId, + parent_def_path: DefPath, + parent_def_id: DefId, + map: &'ast [MapEntry<'ast>], + definitions: Definitions) + -> DefCollector<'ast> { + let mut collector = DefCollector { + krate: krate, + map: map, + parent_def: None, + definitions: definitions, + }; + + assert_eq!(parent_def_path.krate, parent_def_id.krate); + let root_path = Box::new(InlinedRootPath { + data: parent_def_path.data, + def_id: parent_def_id, + }); + + let def = collector.create_def(parent_node, DefPathData::InlinedRoot(root_path)); + collector.parent_def = Some(def); + + collector + } + + fn parent_def(&self) -> Option { + self.parent_def + } + + fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex { + let parent_def = self.parent_def(); + debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); + self.definitions.create_def_with_parent(parent_def, node_id, data) + } + + fn create_def_with_parent(&mut self, + parent: Option, + node_id: NodeId, + data: DefPathData) + -> DefIndex { + self.definitions.create_def_with_parent(parent, node_id, data) + } +} + +impl<'ast> Visitor<'ast> for DefCollector<'ast> { + /// Because we want to track parent items and so forth, enable + /// deep walking so that we walk nested items in the context of + /// their outer items. + fn visit_nested_item(&mut self, item: ItemId) { + debug!("visit_nested_item: {:?}", item); + self.visit_item(self.krate.item(item.id)) + } + + fn visit_item(&mut self, i: &'ast Item) { + debug!("visit_item: {:?}", i); + + // Pick the def data. This need not be unique, but the more + // information we encapsulate into + let def_data = match i.node { + ItemDefaultImpl(..) | ItemImpl(..) => + DefPathData::Impl, + ItemEnum(..) | ItemStruct(..) | ItemTrait(..) | + ItemExternCrate(..) | ItemMod(..) | ItemForeignMod(..) | + ItemTy(..) => + DefPathData::TypeNs(i.name), + ItemStatic(..) | ItemConst(..) | ItemFn(..) => + DefPathData::ValueNs(i.name), + ItemUse(..) => + DefPathData::Misc, + }; + + let def = self.create_def(i.id, def_data); + + let parent_def = self.parent_def; + self.parent_def = Some(def); + + match i.node { + ItemEnum(ref enum_definition, _) => { + for v in &enum_definition.variants { + let variant_def_index = + self.create_def(v.node.data.id(), + DefPathData::EnumVariant(v.node.name)); + + for field in v.node.data.fields() { + self.create_def_with_parent( + Some(variant_def_index), + field.id, + DefPathData::Field(field.name)); + } + } + } + ItemStruct(ref struct_def, _) => { + // If this is a tuple-like struct, register the constructor. + if !struct_def.is_struct() { + self.create_def(struct_def.id(), + DefPathData::StructCtor); + } + + for field in struct_def.fields() { + self.create_def(field.id, DefPathData::Field(field.name)); + } + } + _ => {} + } + intravisit::walk_item(self, i); + self.parent_def = parent_def; + } + + fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { + let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.name)); + + let parent_def = self.parent_def; + self.parent_def = Some(def); + intravisit::walk_foreign_item(self, foreign_item); + self.parent_def = parent_def; + } + + fn visit_generics(&mut self, generics: &'ast Generics) { + for ty_param in generics.ty_params.iter() { + self.create_def(ty_param.id, + DefPathData::TypeParam(ty_param.name)); + } + + intravisit::walk_generics(self, generics); + } + + fn visit_trait_item(&mut self, ti: &'ast TraitItem) { + let def_data = match ti.node { + MethodTraitItem(..) | ConstTraitItem(..) => DefPathData::ValueNs(ti.name), + TypeTraitItem(..) => DefPathData::TypeNs(ti.name), + }; + + let def = self.create_def(ti.id, def_data); + + let parent_def = self.parent_def; + self.parent_def = Some(def); + + match ti.node { + ConstTraitItem(_, Some(ref expr)) => { + self.create_def(expr.id, DefPathData::Initializer); + } + _ => { } + } + + intravisit::walk_trait_item(self, ti); + + self.parent_def = parent_def; + } + + fn visit_impl_item(&mut self, ii: &'ast ImplItem) { + let def_data = match ii.node { + ImplItemKind::Method(..) | ImplItemKind::Const(..) => DefPathData::ValueNs(ii.name), + ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name), + }; + + let def = self.create_def(ii.id, def_data); + + let parent_def = self.parent_def; + self.parent_def = Some(def); + + match ii.node { + ImplItemKind::Const(_, ref expr) => { + self.create_def(expr.id, DefPathData::Initializer); + } + _ => { } + } + + intravisit::walk_impl_item(self, ii); + + self.parent_def = parent_def; + } + + fn visit_pat(&mut self, pat: &'ast Pat) { + let maybe_binding = match pat.node { + PatKind::Ident(_, id, _) => Some(id.node), + _ => None + }; + + let parent_def = self.parent_def; + if let Some(id) = maybe_binding { + let def = self.create_def(pat.id, DefPathData::Binding(id.name)); + self.parent_def = Some(def); + } + + intravisit::walk_pat(self, pat); + self.parent_def = parent_def; + } + + fn visit_expr(&mut self, expr: &'ast Expr) { + let parent_def = self.parent_def; + + if let ExprClosure(..) = expr.node { + let def = self.create_def(expr.id, DefPathData::ClosureExpr); + self.parent_def = Some(def); + } + + intravisit::walk_expr(self, expr); + self.parent_def = parent_def; + } + + fn visit_stmt(&mut self, stmt: &'ast Stmt) { + intravisit::walk_stmt(self, stmt); + } + + fn visit_block(&mut self, block: &'ast Block) { + intravisit::walk_block(self, block); + } + + fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) { + self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name)); + } + + fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) { + self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name)); + } +} diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 6331f7d3009..d0ec83b7eb3 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -10,7 +10,8 @@ pub use self::Node::*; use self::MapEntry::*; -use self::collector::{NodeCollector, DefCollector}; +use self::collector::NodeCollector; +use self::def_collector::DefCollector; pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData, InlinedRootPath}; @@ -36,6 +37,7 @@ use std::mem; pub mod blocks; mod collector; +mod def_collector; pub mod definitions; #[derive(Copy, Clone, Debug)] @@ -852,12 +854,13 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>, ii.visit(&mut collector); { + let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new()); let mut def_collector = DefCollector::extend(map.krate(), ii_parent_id, parent_def_path, parent_def_id, &collector.map, - mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new())); + defs); ii.visit(&mut def_collector); *map.definitions.borrow_mut() = def_collector.definitions; } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index c211fa2925e..488e7ae56ef 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -121,7 +121,7 @@ pub fn compile_input(sess: &Session, let expanded_crate = assign_node_ids(sess, expanded_crate); let dep_graph = DepGraph::new(sess.opts.build_dep_graph); - + // TODO // time(sess.time_passes(), // "external crate/lib resolution",