Auto merge of #33089 - nrc:hir-name-res, r=eddyb

Move def id collection and extern crate handling to before AST->HIR lowering

r? @jseyfried, @eddyb, or @nikomatsakis
This commit is contained in:
bors 2016-04-22 03:41:29 -07:00
commit a264f5b7e8
17 changed files with 766 additions and 439 deletions

View File

@ -62,6 +62,9 @@
// in the HIR, especially for multiple identifiers.
use hir;
use hir::map::Definitions;
use hir::map::definitions::DefPathData;
use hir::def_id::DefIndex;
use std::collections::BTreeMap;
use std::collections::HashMap;
@ -92,10 +95,20 @@ pub struct LoweringContext<'a> {
// A copy of cached_id, but is also set to an id while a node is lowered for
// the first time.
gensym_key: Cell<u32>,
// We must keep the set of definitions up to date as we add nodes that
// weren't in the AST.
definitions: Option<&'a RefCell<Definitions>>,
// As we walk the AST we must keep track of the current 'parent' def id (in
// the form of a DefIndex) so that if we create a new node which introduces
// a definition, then we can properly create the def id.
parent_def: Cell<Option<DefIndex>>,
}
impl<'a, 'hir> LoweringContext<'a> {
pub fn new(id_assigner: &'a NodeIdAssigner, c: Option<&Crate>) -> LoweringContext<'a> {
pub fn new(id_assigner: &'a NodeIdAssigner,
c: Option<&Crate>,
defs: &'a RefCell<Definitions>)
-> LoweringContext<'a> {
let crate_root = c.and_then(|c| {
if std_inject::no_core(c) {
None
@ -113,6 +126,23 @@ impl<'a, 'hir> LoweringContext<'a> {
cached_id: Cell::new(0),
gensym_cache: RefCell::new(HashMap::new()),
gensym_key: Cell::new(0),
definitions: Some(defs),
parent_def: Cell::new(None),
}
}
// Only use this when you want a LoweringContext for testing and won't look
// up def ids for anything created during lowering.
pub fn testing_context(id_assigner: &'a NodeIdAssigner) -> LoweringContext<'a> {
LoweringContext {
crate_root: None,
id_cache: RefCell::new(HashMap::new()),
id_assigner: id_assigner,
cached_id: Cell::new(0),
gensym_cache: RefCell::new(HashMap::new()),
gensym_key: Cell::new(0),
definitions: None,
parent_def: Cell::new(None),
}
}
@ -146,6 +176,25 @@ impl<'a, 'hir> LoweringContext<'a> {
fn diagnostic(&self) -> &Handler {
self.id_assigner.diagnostic()
}
fn with_parent_def<T, F: FnOnce() -> T>(&self, parent_id: NodeId, f: F) -> T {
if self.definitions.is_none() {
// This should only be used for testing.
return f();
}
let old_def = self.parent_def.get();
self.parent_def.set(Some(self.get_def(parent_id)));
let result = f();
self.parent_def.set(old_def);
result
}
fn get_def(&self, id: NodeId) -> DefIndex {
let defs = self.definitions.unwrap().borrow();
defs.opt_def_index(id).unwrap()
}
}
// Utility fn for setting and unsetting the cached id.
@ -733,47 +782,51 @@ pub fn lower_item_kind(lctx: &LoweringContext, i: &ItemKind) -> hir::Item_ {
}
pub fn lower_trait_item(lctx: &LoweringContext, i: &TraitItem) -> hir::TraitItem {
hir::TraitItem {
id: i.id,
name: i.ident.name,
attrs: lower_attrs(lctx, &i.attrs),
node: match i.node {
TraitItemKind::Const(ref ty, ref default) => {
hir::ConstTraitItem(lower_ty(lctx, ty),
default.as_ref().map(|x| lower_expr(lctx, x)))
}
TraitItemKind::Method(ref sig, ref body) => {
hir::MethodTraitItem(lower_method_sig(lctx, sig),
body.as_ref().map(|x| lower_block(lctx, x)))
}
TraitItemKind::Type(ref bounds, ref default) => {
hir::TypeTraitItem(lower_bounds(lctx, bounds),
default.as_ref().map(|x| lower_ty(lctx, x)))
}
},
span: i.span,
}
lctx.with_parent_def(i.id, || {
hir::TraitItem {
id: i.id,
name: i.ident.name,
attrs: lower_attrs(lctx, &i.attrs),
node: match i.node {
TraitItemKind::Const(ref ty, ref default) => {
hir::ConstTraitItem(lower_ty(lctx, ty),
default.as_ref().map(|x| lower_expr(lctx, x)))
}
TraitItemKind::Method(ref sig, ref body) => {
hir::MethodTraitItem(lower_method_sig(lctx, sig),
body.as_ref().map(|x| lower_block(lctx, x)))
}
TraitItemKind::Type(ref bounds, ref default) => {
hir::TypeTraitItem(lower_bounds(lctx, bounds),
default.as_ref().map(|x| lower_ty(lctx, x)))
}
},
span: i.span,
}
})
}
pub fn lower_impl_item(lctx: &LoweringContext, i: &ImplItem) -> hir::ImplItem {
hir::ImplItem {
id: i.id,
name: i.ident.name,
attrs: lower_attrs(lctx, &i.attrs),
vis: lower_visibility(lctx, &i.vis),
defaultness: lower_defaultness(lctx, i.defaultness),
node: match i.node {
ImplItemKind::Const(ref ty, ref expr) => {
hir::ImplItemKind::Const(lower_ty(lctx, ty), lower_expr(lctx, expr))
}
ImplItemKind::Method(ref sig, ref body) => {
hir::ImplItemKind::Method(lower_method_sig(lctx, sig), lower_block(lctx, body))
}
ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(lower_ty(lctx, ty)),
ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
},
span: i.span,
}
lctx.with_parent_def(i.id, || {
hir::ImplItem {
id: i.id,
name: i.ident.name,
attrs: lower_attrs(lctx, &i.attrs),
vis: lower_visibility(lctx, &i.vis),
defaultness: lower_defaultness(lctx, i.defaultness),
node: match i.node {
ImplItemKind::Const(ref ty, ref expr) => {
hir::ImplItemKind::Const(lower_ty(lctx, ty), lower_expr(lctx, expr))
}
ImplItemKind::Method(ref sig, ref body) => {
hir::ImplItemKind::Method(lower_method_sig(lctx, sig), lower_block(lctx, body))
}
ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(lower_ty(lctx, ty)),
ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
},
span: i.span,
}
})
}
pub fn lower_mod(lctx: &LoweringContext, m: &Mod) -> hir::Mod {
@ -831,7 +884,9 @@ pub fn lower_item_id(_lctx: &LoweringContext, i: &Item) -> hir::ItemId {
}
pub fn lower_item(lctx: &LoweringContext, i: &Item) -> hir::Item {
let node = lower_item_kind(lctx, &i.node);
let node = lctx.with_parent_def(i.id, || {
lower_item_kind(lctx, &i.node)
});
hir::Item {
id: i.id,
@ -844,21 +899,23 @@ pub fn lower_item(lctx: &LoweringContext, i: &Item) -> hir::Item {
}
pub fn lower_foreign_item(lctx: &LoweringContext, i: &ForeignItem) -> hir::ForeignItem {
hir::ForeignItem {
id: i.id,
name: i.ident.name,
attrs: lower_attrs(lctx, &i.attrs),
node: match i.node {
ForeignItemKind::Fn(ref fdec, ref generics) => {
hir::ForeignItemFn(lower_fn_decl(lctx, fdec), lower_generics(lctx, generics))
}
ForeignItemKind::Static(ref t, m) => {
hir::ForeignItemStatic(lower_ty(lctx, t), m)
}
},
vis: lower_visibility(lctx, &i.vis),
span: i.span,
}
lctx.with_parent_def(i.id, || {
hir::ForeignItem {
id: i.id,
name: i.ident.name,
attrs: lower_attrs(lctx, &i.attrs),
node: match i.node {
ForeignItemKind::Fn(ref fdec, ref generics) => {
hir::ForeignItemFn(lower_fn_decl(lctx, fdec), lower_generics(lctx, generics))
}
ForeignItemKind::Static(ref t, m) => {
hir::ForeignItemStatic(lower_ty(lctx, t), m)
}
},
vis: lower_visibility(lctx, &i.vis),
span: i.span,
}
})
}
pub fn lower_method_sig(lctx: &LoweringContext, sig: &MethodSig) -> hir::MethodSig {
@ -926,9 +983,11 @@ pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
node: match p.node {
PatKind::Wild => hir::PatKind::Wild,
PatKind::Ident(ref binding_mode, pth1, ref sub) => {
hir::PatKind::Ident(lower_binding_mode(lctx, binding_mode),
respan(pth1.span, lower_ident(lctx, pth1.node)),
sub.as_ref().map(|x| lower_pat(lctx, x)))
lctx.with_parent_def(p.id, || {
hir::PatKind::Ident(lower_binding_mode(lctx, binding_mode),
respan(pth1.span, lower_ident(lctx, pth1.node)),
sub.as_ref().map(|x| lower_pat(lctx, x)))
})
}
PatKind::Lit(ref e) => hir::PatKind::Lit(lower_expr(lctx, e)),
PatKind::TupleStruct(ref pth, ref pats) => {
@ -1202,9 +1261,11 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
hir::MatchSource::Normal)
}
ExprKind::Closure(capture_clause, ref decl, ref body) => {
hir::ExprClosure(lower_capture_clause(lctx, capture_clause),
lower_fn_decl(lctx, decl),
lower_block(lctx, body))
lctx.with_parent_def(e.id, || {
hir::ExprClosure(lower_capture_clause(lctx, capture_clause),
lower_fn_decl(lctx, decl),
lower_block(lctx, body))
})
}
ExprKind::Block(ref blk) => hir::ExprBlock(lower_block(lctx, blk)),
ExprKind::Assign(ref el, ref er) => {
@ -1602,7 +1663,12 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
// `{ let _result = ...; _result }`
// underscore prevents an unused_variables lint if the head diverges
let result_ident = lctx.str_to_ident("_result");
let let_stmt = stmt_let(lctx, e.span, false, result_ident, match_expr, None);
let let_stmt = stmt_let(lctx,
e.span,
false,
result_ident,
match_expr,
None);
let result = expr_ident(lctx, e.span, result_ident, None);
let block = block_all(lctx, e.span, hir_vec![let_stmt], Some(result));
// add the attributes to the outer returned expr node
@ -1655,7 +1721,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
let err_ctor = expr_path(lctx, path, None);
expr_call(lctx, e.span, err_ctor, hir_vec![from_expr], None)
};
let err_pat = pat_err(lctx, e.span, pat_ident(lctx, e.span, err_ident));
let err_pat = pat_err(lctx, e.span,
pat_ident(lctx, e.span, err_ident));
let ret_expr = expr(lctx, e.span,
hir::Expr_::ExprRet(Some(err_expr)), None);
@ -1938,12 +2005,22 @@ fn pat_ident_binding_mode(lctx: &LoweringContext,
bm: hir::BindingMode)
-> P<hir::Pat> {
let pat_ident = hir::PatKind::Ident(bm,
Spanned {
span: span,
node: ident,
},
None);
pat(lctx, span, pat_ident)
Spanned {
span: span,
node: ident,
},
None);
let pat = pat(lctx, span, pat_ident);
if let Some(defs) = lctx.definitions {
let mut defs = defs.borrow_mut();
defs.create_def_with_parent(lctx.parent_def.get(),
pat.id,
DefPathData::Binding(ident.name));
}
pat
}
fn pat_wild(lctx: &LoweringContext, span: Span) -> P<hir::Pat> {
@ -2130,7 +2207,8 @@ mod test {
let ast_in = quote_expr!(&cx, in HEAP { foo() });
let ast_in = assigner.fold_expr(ast_in);
let lctx = LoweringContext::new(&assigner, None);
let lctx = LoweringContext::testing_context(&assigner);
let hir1 = lower_expr(&lctx, &ast_if_let);
let hir2 = lower_expr(&lctx, &ast_if_let);
assert!(hir1 == hir2);

View File

@ -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,18 +13,16 @@ 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 an AST and collects Node's into an AST
/// Map.
/// A Visitor that walks over the HIR and collects Node's into a HIR map.
pub struct NodeCollector<'ast> {
pub krate: &'ast Crate,
pub map: Vec<MapEntry<'ast>>,
pub definitions: Definitions,
pub parent_node: NodeId,
}
@ -33,16 +31,10 @@ impl<'ast> NodeCollector<'ast> {
let mut collector = NodeCollector {
krate: krate,
map: vec![],
definitions: Definitions::new(),
parent_node: CRATE_NODE_ID,
};
collector.insert_entry(CRATE_NODE_ID, RootCrate);
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
}
@ -51,53 +43,20 @@ impl<'ast> NodeCollector<'ast> {
parent_node: NodeId,
parent_def_path: DefPath,
parent_def_id: DefId,
map: Vec<MapEntry<'ast>>,
definitions: Definitions)
map: Vec<MapEntry<'ast>>)
-> NodeCollector<'ast> {
let mut collector = NodeCollector {
krate: krate,
map: map,
parent_node: parent_node,
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,
});
collector.insert_entry(parent_node, RootInlinedParent(parent));
collector.create_def(parent_node, DefPathData::InlinedRoot(root_path));
collector
}
fn parent_def(&self) -> Option<DefIndex> {
let mut parent_node = Some(self.parent_node);
while let Some(p) = parent_node {
if let Some(q) = self.definitions.opt_def_index(p) {
return Some(q);
}
parent_node = self.map[p as usize].parent_node();
}
None
}
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<DefIndex>,
node_id: NodeId,
data: DefPathData)
-> DefIndex {
self.definitions.create_def_with_parent(parent, node_id, data)
}
fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
debug!("ast_map: {:?} => {:?}", id, entry);
let len = self.map.len();
@ -107,15 +66,17 @@ impl<'ast> NodeCollector<'ast> {
self.map[id as usize] = entry;
}
fn insert_def(&mut self, id: NodeId, node: Node<'ast>, data: DefPathData) -> DefIndex {
self.insert(id, node);
self.create_def(id, data)
}
fn insert(&mut self, id: NodeId, node: Node<'ast>) {
let entry = MapEntry::from_node(self.parent_node, node);
self.insert_entry(id, entry);
}
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_id: NodeId, f: F) {
let parent_node = self.parent_node;
self.parent_node = parent_id;
f(self);
self.parent_node = parent_node;
}
}
impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
@ -130,188 +91,104 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
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,
};
self.insert(i.id, NodeItem(i));
self.insert_def(i.id, NodeItem(i), def_data);
let parent_node = self.parent_node;
self.parent_node = i.id;
match i.node {
ItemImpl(..) => {}
ItemEnum(ref enum_definition, _) => {
for v in &enum_definition.variants {
let variant_def_index =
self.insert_def(v.node.data.id(),
NodeVariant(v),
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));
self.with_parent(i.id, |this| {
match i.node {
ItemEnum(ref enum_definition, _) => {
for v in &enum_definition.variants {
this.insert(v.node.data.id(), NodeVariant(v));
}
}
}
ItemForeignMod(..) => {
}
ItemStruct(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
self.insert_def(struct_def.id(),
NodeStructCtor(struct_def),
DefPathData::StructCtor);
}
for field in struct_def.fields() {
self.create_def(field.id, DefPathData::Field(field.name));
}
}
ItemTrait(_, _, ref bounds, _) => {
for b in bounds.iter() {
if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
self.insert(t.trait_ref.ref_id, NodeItem(i));
ItemStruct(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
this.insert(struct_def.id(), NodeStructCtor(struct_def));
}
}
}
ItemUse(ref view_path) => {
match view_path.node {
ViewPathList(_, ref paths) => {
for path in paths {
self.insert(path.node.id(), NodeItem(i));
ItemTrait(_, _, ref bounds, _) => {
for b in bounds.iter() {
if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
this.insert(t.trait_ref.ref_id, NodeItem(i));
}
}
_ => ()
}
ItemUse(ref view_path) => {
match view_path.node {
ViewPathList(_, ref paths) => {
for path in paths {
this.insert(path.node.id(), NodeItem(i));
}
}
_ => ()
}
}
_ => {}
}
_ => {}
}
intravisit::walk_item(self, i);
self.parent_node = parent_node;
intravisit::walk_item(this, i);
});
}
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
self.insert_def(foreign_item.id,
NodeForeignItem(foreign_item),
DefPathData::ValueNs(foreign_item.name));
self.insert(foreign_item.id, NodeForeignItem(foreign_item));
let parent_node = self.parent_node;
self.parent_node = foreign_item.id;
intravisit::walk_foreign_item(self, foreign_item);
self.parent_node = parent_node;
self.with_parent(foreign_item.id, |this| {
intravisit::walk_foreign_item(this, foreign_item);
});
}
fn visit_generics(&mut self, generics: &'ast Generics) {
for ty_param in generics.ty_params.iter() {
self.insert_def(ty_param.id,
NodeTyParam(ty_param),
DefPathData::TypeParam(ty_param.name));
self.insert(ty_param.id, NodeTyParam(ty_param));
}
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),
};
self.insert(ti.id, NodeTraitItem(ti));
self.create_def(ti.id, def_data);
let parent_node = self.parent_node;
self.parent_node = ti.id;
match ti.node {
ConstTraitItem(_, Some(ref expr)) => {
self.create_def(expr.id, DefPathData::Initializer);
}
_ => { }
}
intravisit::walk_trait_item(self, ti);
self.parent_node = parent_node;
self.with_parent(ti.id, |this| {
intravisit::walk_trait_item(this, ti);
});
}
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),
};
self.insert(ii.id, NodeImplItem(ii));
self.insert_def(ii.id, NodeImplItem(ii), def_data);
let parent_node = self.parent_node;
self.parent_node = ii.id;
match ii.node {
ImplItemKind::Const(_, ref expr) => {
self.create_def(expr.id, DefPathData::Initializer);
}
_ => { }
}
intravisit::walk_impl_item(self, ii);
self.parent_node = parent_node;
self.with_parent(ii.id, |this| {
intravisit::walk_impl_item(this, ii);
});
}
fn visit_pat(&mut self, pat: &'ast Pat) {
let maybe_binding = match pat.node {
PatKind::Ident(_, id, _) => Some(id.node),
_ => None
};
if let Some(id) = maybe_binding {
self.insert_def(pat.id, NodeLocal(pat), DefPathData::Binding(id.name));
let node = if let PatKind::Ident(..) = pat.node {
NodeLocal(pat)
} else {
self.insert(pat.id, NodePat(pat));
}
NodePat(pat)
};
self.insert(pat.id, node);
let parent_node = self.parent_node;
self.parent_node = pat.id;
intravisit::walk_pat(self, pat);
self.parent_node = parent_node;
self.with_parent(pat.id, |this| {
intravisit::walk_pat(this, pat);
});
}
fn visit_expr(&mut self, expr: &'ast Expr) {
self.insert(expr.id, NodeExpr(expr));
match expr.node {
ExprClosure(..) => { self.create_def(expr.id, DefPathData::ClosureExpr); }
_ => { }
}
let parent_node = self.parent_node;
self.parent_node = expr.id;
intravisit::walk_expr(self, expr);
self.parent_node = parent_node;
self.with_parent(expr.id, |this| {
intravisit::walk_expr(this, expr);
});
}
fn visit_stmt(&mut self, stmt: &'ast Stmt) {
let id = stmt.node.id();
self.insert(id, NodeStmt(stmt));
let parent_node = self.parent_node;
self.parent_node = id;
intravisit::walk_stmt(self, stmt);
self.parent_node = parent_node;
self.with_parent(id, |this| {
intravisit::walk_stmt(this, stmt);
});
}
fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
@ -322,22 +199,12 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
fn visit_block(&mut self, block: &'ast Block) {
self.insert(block.id, NodeBlock(block));
let parent_node = self.parent_node;
self.parent_node = block.id;
intravisit::walk_block(self, block);
self.parent_node = parent_node;
self.with_parent(block.id, |this| {
intravisit::walk_block(this, block);
});
}
fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
self.insert(lifetime.id, NodeLifetime(lifetime));
}
fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
self.visit_lifetime(&def.lifetime);
}
fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
}
}

View File

@ -0,0 +1,384 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::*;
use hir;
use hir::intravisit;
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
use middle::cstore::InlinedItem;
use syntax::ast::*;
use syntax::visit;
use syntax::parse::token;
/// Creates def ids for nodes in the HIR.
pub struct DefCollector<'ast> {
// If we are walking HIR (c.f., AST), we need to keep a reference to the
// crate.
hir_crate: Option<&'ast hir::Crate>,
pub definitions: Definitions,
parent_def: Option<DefIndex>,
}
impl<'ast> DefCollector<'ast> {
pub fn root() -> DefCollector<'ast> {
let mut collector = DefCollector {
hir_crate: None,
definitions: Definitions::new(),
parent_def: None,
};
let root = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
assert_eq!(root, CRATE_DEF_INDEX);
collector.parent_def = Some(root);
collector.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
collector
}
pub fn extend(parent_node: NodeId,
parent_def_path: DefPath,
parent_def_id: DefId,
definitions: Definitions)
-> DefCollector<'ast> {
let mut collector = DefCollector {
hir_crate: None,
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
}
pub fn walk_item(&mut self, ii: &'ast InlinedItem, krate: &'ast hir::Crate) {
self.hir_crate = Some(krate);
ii.visit(self);
}
fn parent_def(&self) -> Option<DefIndex> {
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<DefIndex>,
node_id: NodeId,
data: DefPathData)
-> DefIndex {
self.definitions.create_def_with_parent(parent, node_id, data)
}
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
let parent = self.parent_def;
self.parent_def = Some(parent_def);
f(self);
self.parent_def = parent;
}
}
impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
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 {
ItemKind::DefaultImpl(..) | ItemKind::Impl(..) =>
DefPathData::Impl,
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Trait(..) |
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
DefPathData::TypeNs(i.ident.name),
ItemKind::Mod(..) => DefPathData::Module(i.ident.name),
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
DefPathData::ValueNs(i.ident.name),
ItemKind::Mac(..) => DefPathData::MacroDef(i.ident.name),
ItemKind::Use(..) => DefPathData::Misc,
};
let def = self.create_def(i.id, def_data);
self.with_parent(def, |this| {
match i.node {
ItemKind::Enum(ref enum_definition, _) => {
for v in &enum_definition.variants {
let variant_def_index =
this.create_def(v.node.data.id(),
DefPathData::EnumVariant(v.node.name.name));
for (index, field) in v.node.data.fields().iter().enumerate() {
let name = field.ident.map(|ident| ident.name)
.unwrap_or(token::intern(&index.to_string()));
this.create_def_with_parent(Some(variant_def_index),
field.id,
DefPathData::Field(name));
}
}
}
ItemKind::Struct(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
this.create_def(struct_def.id(),
DefPathData::StructCtor);
}
for (index, field) in struct_def.fields().iter().enumerate() {
let name = field.ident.map(|ident| ident.name)
.unwrap_or(token::intern(&index.to_string()));
this.create_def(field.id, DefPathData::Field(name));
}
}
_ => {}
}
visit::walk_item(this, i);
});
}
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.ident.name));
self.with_parent(def, |this| {
visit::walk_foreign_item(this, foreign_item);
});
}
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.ident.name));
}
visit::walk_generics(self, generics);
}
fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
let def_data = match ti.node {
TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
DefPathData::ValueNs(ti.ident.name),
TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name),
};
let def = self.create_def(ti.id, def_data);
self.with_parent(def, |this| {
if let TraitItemKind::Const(_, Some(ref expr)) = ti.node {
this.create_def(expr.id, DefPathData::Initializer);
}
visit::walk_trait_item(this, ti);
});
}
fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
let def_data = match ii.node {
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
DefPathData::ValueNs(ii.ident.name),
ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name),
ImplItemKind::Macro(..) => DefPathData::MacroDef(ii.ident.name),
};
let def = self.create_def(ii.id, def_data);
self.with_parent(def, |this| {
if let ImplItemKind::Const(_, ref expr) = ii.node {
this.create_def(expr.id, DefPathData::Initializer);
}
visit::walk_impl_item(this, ii);
});
}
fn visit_pat(&mut self, pat: &'ast Pat) {
let parent_def = self.parent_def;
if let PatKind::Ident(_, id, _) = pat.node {
let def = self.create_def(pat.id, DefPathData::Binding(id.node.name));
self.parent_def = Some(def);
}
visit::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 ExprKind::Closure(..) = expr.node {
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
self.parent_def = Some(def);
}
visit::walk_expr(self, expr);
self.parent_def = parent_def;
}
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.ident.name));
}
}
// We walk the HIR rather than the AST when reading items from metadata.
impl<'ast> intravisit::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_id: hir::ItemId) {
debug!("visit_nested_item: {:?}", item_id);
let item = self.hir_crate.unwrap().item(item_id.id);
self.visit_item(item)
}
fn visit_item(&mut self, i: &'ast hir::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 {
hir::ItemDefaultImpl(..) | hir::ItemImpl(..) =>
DefPathData::Impl,
hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
hir::ItemExternCrate(..) | hir::ItemMod(..) | hir::ItemForeignMod(..) |
hir::ItemTy(..) =>
DefPathData::TypeNs(i.name),
hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) =>
DefPathData::ValueNs(i.name),
hir::ItemUse(..) => DefPathData::Misc,
};
let def = self.create_def(i.id, def_data);
self.with_parent(def, |this| {
match i.node {
hir::ItemEnum(ref enum_definition, _) => {
for v in &enum_definition.variants {
let variant_def_index =
this.create_def(v.node.data.id(),
DefPathData::EnumVariant(v.node.name));
for field in v.node.data.fields() {
this.create_def_with_parent(Some(variant_def_index),
field.id,
DefPathData::Field(field.name));
}
}
}
hir::ItemStruct(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
this.create_def(struct_def.id(),
DefPathData::StructCtor);
}
for field in struct_def.fields() {
this.create_def(field.id, DefPathData::Field(field.name));
}
}
_ => {}
}
intravisit::walk_item(this, i);
});
}
fn visit_foreign_item(&mut self, foreign_item: &'ast hir::ForeignItem) {
let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.name));
self.with_parent(def, |this| {
intravisit::walk_foreign_item(this, foreign_item);
});
}
fn visit_generics(&mut self, generics: &'ast hir::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 hir::TraitItem) {
let def_data = match ti.node {
hir::MethodTraitItem(..) | hir::ConstTraitItem(..) =>
DefPathData::ValueNs(ti.name),
hir::TypeTraitItem(..) => DefPathData::TypeNs(ti.name),
};
let def = self.create_def(ti.id, def_data);
self.with_parent(def, |this| {
if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node {
this.create_def(expr.id, DefPathData::Initializer);
}
intravisit::walk_trait_item(this, ti);
});
}
fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
let def_data = match ii.node {
hir::ImplItemKind::Method(..) | hir::ImplItemKind::Const(..) =>
DefPathData::ValueNs(ii.name),
hir::ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name),
};
let def = self.create_def(ii.id, def_data);
self.with_parent(def, |this| {
if let hir::ImplItemKind::Const(_, ref expr) = ii.node {
this.create_def(expr.id, DefPathData::Initializer);
}
intravisit::walk_impl_item(this, ii);
});
}
fn visit_pat(&mut self, pat: &'ast hir::Pat) {
let parent_def = self.parent_def;
if let hir::PatKind::Ident(_, id, _) = pat.node {
let def = self.create_def(pat.id, DefPathData::Binding(id.node.name));
self.parent_def = Some(def);
}
intravisit::walk_pat(self, pat);
self.parent_def = parent_def;
}
fn visit_expr(&mut self, expr: &'ast hir::Expr) {
let parent_def = self.parent_def;
if let hir::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_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) {
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
}
fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) {
self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
}
}

View File

@ -11,6 +11,7 @@
pub use self::Node::*;
use self::MapEntry::*;
use self::collector::NodeCollector;
use self::def_collector::DefCollector;
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
DisambiguatedDefPathData, InlinedRootPath};
@ -21,9 +22,10 @@ use middle::cstore::InlinedItem as II;
use hir::def_id::{CRATE_DEF_INDEX, DefId};
use syntax::abi::Abi;
use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID};
use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, };
use syntax::attr::ThinAttributesExt;
use syntax::codemap::{Span, Spanned};
use syntax::visit;
use hir::*;
use hir::fold::Folder;
@ -36,6 +38,7 @@ use std::mem;
pub mod blocks;
mod collector;
mod def_collector;
pub mod definitions;
#[derive(Copy, Clone, Debug)]
@ -193,7 +196,7 @@ pub struct Map<'ast> {
/// plain old integers.
map: RefCell<Vec<MapEntry<'ast>>>,
definitions: RefCell<Definitions>,
definitions: &'ast RefCell<Definitions>,
}
impl<'ast> Map<'ast> {
@ -780,12 +783,18 @@ impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
}
}
pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
let (map, definitions) = {
let mut collector = NodeCollector::root(&forest.krate);
intravisit::walk_crate(&mut collector, &forest.krate);
(collector.map, collector.definitions)
};
pub fn collect_definitions<'ast>(krate: &'ast ast::Crate) -> Definitions {
let mut def_collector = DefCollector::root();
visit::walk_crate(&mut def_collector, krate);
def_collector.definitions
}
pub fn map_crate<'ast>(forest: &'ast mut Forest,
definitions: &'ast RefCell<Definitions>)
-> Map<'ast> {
let mut collector = NodeCollector::root(&forest.krate);
intravisit::walk_crate(&mut collector, &forest.krate);
let map = collector.map;
if log_enabled!(::log::DEBUG) {
// This only makes sense for ordered stores; note the
@ -807,7 +816,7 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
forest: forest,
dep_graph: forest.dep_graph.clone(),
map: RefCell::new(map),
definitions: RefCell::new(definitions),
definitions: definitions,
}
}
@ -834,21 +843,24 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
};
let ii = map.forest.inlined_items.alloc(ii);
let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
let mut collector =
NodeCollector::extend(
map.krate(),
ii,
ii_parent_id,
parent_def_path,
parent_def_id,
mem::replace(&mut *map.map.borrow_mut(), vec![]),
mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new()));
ii.visit(&mut collector);
let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
let mut def_collector = DefCollector::extend(ii_parent_id,
parent_def_path.clone(),
parent_def_id,
defs);
def_collector.walk_item(ii, map.krate());
*map.definitions.borrow_mut() = def_collector.definitions;
let mut collector = NodeCollector::extend(map.krate(),
ii,
ii_parent_id,
parent_def_path,
parent_def_id,
mem::replace(&mut *map.map.borrow_mut(), vec![]));
ii.visit(&mut collector);
*map.map.borrow_mut() = collector.map;
*map.definitions.borrow_mut() = collector.definitions;
ii
}

View File

@ -43,6 +43,7 @@ use super::Compilation;
use serialize::json;
use std::cell::RefCell;
use std::collections::HashMap;
use std::env;
use std::ffi::{OsString, OsStr};
@ -120,13 +121,24 @@ pub fn compile_input(sess: &Session,
Ok(()));
let expanded_crate = assign_node_ids(sess, expanded_crate);
// Lower ast -> hir.
let lcx = LoweringContext::new(sess, Some(&expanded_crate));
let dep_graph = DepGraph::new(sess.opts.build_dep_graph());
let mut hir_forest = time(sess.time_passes(),
"lowering ast -> hir",
|| hir_map::Forest::new(lower_crate(&lcx, &expanded_crate),
dep_graph));
// Collect defintions for def ids.
let defs = &RefCell::new(time(sess.time_passes(),
"collecting defs",
|| hir_map::collect_definitions(&expanded_crate)));
time(sess.time_passes(),
"external crate/lib resolution",
|| LocalCrateReader::new(sess, &cstore, &defs, &expanded_crate, &id)
.read_crates(&dep_graph));
// Lower ast -> hir.
let lcx = LoweringContext::new(sess, Some(&expanded_crate), defs);
let hir_forest = &mut time(sess.time_passes(),
"lowering ast -> hir",
|| hir_map::Forest::new(lower_crate(&lcx, &expanded_crate),
dep_graph));
// Discard MTWT tables that aren't required past lowering to HIR.
if !sess.opts.debugging_opts.keep_mtwt_tables &&
@ -135,7 +147,12 @@ pub fn compile_input(sess: &Session,
}
let arenas = ty::CtxtArenas::new();
let hir_map = make_map(sess, &mut hir_forest);
// Construct the HIR map
let hir_map = time(sess.time_passes(),
"indexing hir",
move || hir_map::map_crate(hir_forest, defs));
write_out_deps(sess, &outputs, &id);
@ -171,7 +188,6 @@ pub fn compile_input(sess: &Session,
};
phase_3_run_analysis_passes(sess,
&cstore,
hir_map,
&arenas,
&id,
@ -726,20 +742,10 @@ pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate {
krate
}
pub fn make_map<'ast>(sess: &Session,
forest: &'ast mut hir_map::Forest)
-> hir_map::Map<'ast> {
// Construct the HIR map
time(sess.time_passes(),
"indexing hir",
move || hir_map::map_crate(forest))
}
/// Run the resolution, typechecking, region checking and other
/// miscellaneous analysis passes on the crate. Return various
/// structures carrying the results of the analysis.
pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
cstore: &CStore,
hir_map: hir_map::Map<'tcx>,
arenas: &'tcx ty::CtxtArenas<'tcx>,
name: &str,
@ -762,10 +768,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
let time_passes = sess.time_passes();
time(time_passes,
"external crate/lib resolution",
|| LocalCrateReader::new(sess, cstore, &hir_map, name).read_crates());
let lang_items = time(time_passes, "language item collection", || {
sess.track_errors(|| {
middle::lang_items::collect_language_items(&sess, &hir_map)
@ -778,8 +780,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
export_map,
trait_map,
glob_map,
} = time(time_passes,
"resolution",
} = time(sess.time_passes(),
"name resolution",
|| resolve::resolve_crate(sess, &hir_map, make_glob_map));
let mut analysis = ty::CrateAnalysis {

View File

@ -199,14 +199,9 @@ pub fn run_compiler<'a>(args: &[String],
// It is somewhat unfortunate that this is hardwired in - this is forced by
// the fact that pretty_print_input requires the session by value.
let pretty = callbacks.parse_pretty(&sess, &matches);
match pretty {
Some((ppm, opt_uii)) => {
pretty::pretty_print_input(sess, &cstore, cfg, &input, ppm, opt_uii, ofile);
return (Ok(()), None);
}
None => {
// continue
}
if let Some((ppm, opt_uii)) = pretty {
pretty::pretty_print_input(sess, &cstore, cfg, &input, ppm, opt_uii, ofile);
return (Ok(()), None);
}
let plugins = sess.opts.debugging_opts.extra_plugins.clone();

View File

@ -29,6 +29,7 @@ use rustc_borrowck as borrowck;
use rustc_borrowck::graphviz as borrowck_dot;
use rustc_resolve as resolve;
use rustc_metadata::cstore::CStore;
use rustc_metadata::creader::LocalCrateReader;
use rustc_mir::pretty::write_mir_pretty;
use rustc_mir::graphviz::write_mir_graphviz;
@ -43,6 +44,7 @@ use syntax::util::small_vector::SmallVector;
use graphviz as dot;
use std::cell::RefCell;
use std::fs::File;
use std::io::{self, Write};
use std::iter;
@ -179,7 +181,6 @@ impl PpSourceMode {
}
fn call_with_pp_support_hir<'tcx, A, B, F>(&self,
sess: &'tcx Session,
cstore: &CStore,
ast_map: &hir_map::Map<'tcx>,
arenas: &'tcx ty::CtxtArenas<'tcx>,
id: &str,
@ -206,7 +207,6 @@ impl PpSourceMode {
}
PpmTyped => {
abort_on_err(driver::phase_3_run_analysis_passes(sess,
cstore,
ast_map.clone(),
arenas,
id,
@ -721,7 +721,7 @@ pub fn pretty_print_input(sess: Session,
let is_expanded = needs_expansion(&ppm);
let compute_ast_map = needs_ast_map(&ppm, &opt_uii);
let krate = if compute_ast_map {
match driver::phase_2_configure_and_expand(&sess, &cstore, krate, &id[..], None) {
match driver::phase_2_configure_and_expand(&sess, &cstore, krate, &id, None) {
Err(_) => return,
Ok(k) => driver::assign_node_ids(&sess, k),
}
@ -732,14 +732,18 @@ pub fn pretty_print_input(sess: Session,
// There is some twisted, god-forsaken tangle of lifetimes here which makes
// the ordering of stuff super-finicky.
let mut hir_forest;
let lcx = LoweringContext::new(&sess, Some(&krate));
let arenas = ty::CtxtArenas::new();
let mut _defs = None;
let dep_graph = DepGraph::new(false);
let arenas = ty::CtxtArenas::new();
let _ignore = dep_graph.in_ignore();
let ast_map = if compute_ast_map {
_defs = Some(RefCell::new(hir_map::collect_definitions(&krate)));
let defs = _defs.as_ref().unwrap();
LocalCrateReader::new(&sess, &cstore, defs, &krate, &id).read_crates(&dep_graph);
let lcx = LoweringContext::new(&sess, Some(&krate), defs);
hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph.clone());
let map = driver::make_map(&sess, &mut hir_forest);
Some(map)
Some(hir_map::map_crate(&mut hir_forest, defs))
} else {
None
};
@ -752,7 +756,7 @@ pub fn pretty_print_input(sess: Session,
.unwrap()
.as_bytes()
.to_vec();
let mut rdr = &src[..];
let mut rdr = &*src;
let mut out = Vec::new();
@ -777,7 +781,6 @@ pub fn pretty_print_input(sess: Session,
(PpmHir(s), None) => {
let out: &mut Write = &mut out;
s.call_with_pp_support_hir(&sess,
cstore,
&ast_map.unwrap(),
&arenas,
&id,
@ -799,7 +802,6 @@ pub fn pretty_print_input(sess: Session,
(PpmHir(s), Some(uii)) => {
let out: &mut Write = &mut out;
s.call_with_pp_support_hir(&sess,
cstore,
&ast_map.unwrap(),
&arenas,
&id,
@ -840,7 +842,6 @@ pub fn pretty_print_input(sess: Session,
None
};
abort_on_err(driver::phase_3_run_analysis_passes(&sess,
&cstore,
ast_map,
&arenas,
&id,
@ -887,7 +888,6 @@ pub fn pretty_print_input(sess: Session,
Some(code) => {
let variants = gather_flowgraph_variants(&sess);
abort_on_err(driver::phase_3_run_analysis_passes(&sess,
&cstore,
ast_map,
&arenas,
&id,

View File

@ -27,8 +27,10 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::relate::TypeRelation;
use rustc::infer::{self, InferOk, InferResult, TypeOrigin};
use rustc_metadata::cstore::CStore;
use rustc_metadata::creader::LocalCrateReader;
use rustc::hir::map as hir_map;
use rustc::session::{self, config};
use std::cell::RefCell;
use std::rc::Rc;
use syntax::ast;
use syntax::abi::Abi;
@ -119,13 +121,15 @@ fn test_env<F>(source_string: &str,
let krate = driver::phase_2_configure_and_expand(&sess, &cstore, krate, "test", None)
.expect("phase 2 aborted");
let krate = driver::assign_node_ids(&sess, krate);
let lcx = LoweringContext::new(&sess, Some(&krate));
let dep_graph = DepGraph::new(false);
let krate = driver::assign_node_ids(&sess, krate);
let defs = &RefCell::new(hir_map::collect_definitions(&krate));
LocalCrateReader::new(&sess, &cstore, defs, &krate, "test_crate").read_crates(&dep_graph);
let lcx = LoweringContext::new(&sess, Some(&krate), defs);
let _ignore = dep_graph.in_ignore();
let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph.clone());
let mut hir_forest = &mut hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph.clone());
let arenas = ty::CtxtArenas::new();
let ast_map = driver::make_map(&sess, &mut hir_forest);
let ast_map = hir_map::map_crate(hir_forest, defs);
// run just enough stuff to build a tcx:
let lang_items = lang_items::collect_language_items(&sess, &ast_map);

View File

@ -1339,7 +1339,7 @@ fn roundtrip(in_item: hir::Item) {
fn test_basic() {
let cx = mk_ctxt();
let fnia = FakeNodeIdAssigner;
let lcx = LoweringContext::new(&fnia, None);
let lcx = LoweringContext::testing_context(&fnia);
roundtrip(lower_item(&lcx, &quote_item!(&cx,
fn foo() {}
).unwrap()));
@ -1349,7 +1349,7 @@ fn test_basic() {
fn test_smalltalk() {
let cx = mk_ctxt();
let fnia = FakeNodeIdAssigner;
let lcx = LoweringContext::new(&fnia, None);
let lcx = LoweringContext::testing_context(&fnia);
roundtrip(lower_item(&lcx, &quote_item!(&cx,
fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed.
).unwrap()));
@ -1359,7 +1359,7 @@ fn test_smalltalk() {
fn test_more() {
let cx = mk_ctxt();
let fnia = FakeNodeIdAssigner;
let lcx = LoweringContext::new(&fnia, None);
let lcx = LoweringContext::testing_context(&fnia);
roundtrip(lower_item(&lcx, &quote_item!(&cx,
fn foo(x: usize, y: usize) -> usize {
let z = x + y;
@ -1378,7 +1378,7 @@ fn test_simplification() {
}
).unwrap();
let fnia = FakeNodeIdAssigner;
let lcx = LoweringContext::new(&fnia, None);
let lcx = LoweringContext::testing_context(&fnia);
let hir_item = lower_item(&lcx, &item);
let item_in = InlinedItemRef::Item(&hir_item);
let item_out = simplify_ast(item_in);

View File

@ -18,7 +18,7 @@ use decoder;
use loader::{self, CratePaths};
use rustc::hir::svh::Svh;
use rustc::dep_graph::DepNode;
use rustc::dep_graph::{DepGraph, DepNode};
use rustc::session::{config, Session};
use rustc::session::search_paths::PathKind;
use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
@ -37,15 +37,15 @@ use syntax::parse;
use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::parse::token::InternedString;
use rustc::hir::intravisit::Visitor;
use rustc::hir;
use syntax::visit;
use log;
pub struct LocalCrateReader<'a, 'b:'a> {
pub struct LocalCrateReader<'a> {
sess: &'a Session,
cstore: &'a CStore,
creader: CrateReader<'a>,
ast_map: &'a hir_map::Map<'b>,
krate: &'a ast::Crate,
defintions: &'a RefCell<hir_map::Definitions>,
}
pub struct CrateReader<'a> {
@ -56,9 +56,10 @@ pub struct CrateReader<'a> {
local_crate_name: String,
}
impl<'a, 'b, 'hir> Visitor<'hir> for LocalCrateReader<'a, 'b> {
fn visit_item(&mut self, a: &'hir hir::Item) {
impl<'a, 'ast> visit::Visitor<'ast> for LocalCrateReader<'a> {
fn visit_item(&mut self, a: &'ast ast::Item) {
self.process_item(a);
visit::walk_item(self, a);
}
}
@ -80,11 +81,8 @@ fn dump_crates(cstore: &CStore) {
fn should_link(i: &ast::Item) -> bool {
!attr::contains_name(&i.attrs, "no_link")
}
// Dup for the hir
fn should_link_hir(i: &hir::Item) -> bool {
!attr::contains_name(&i.attrs, "no_link")
}
#[derive(Debug)]
struct CrateInfo {
ident: String,
name: String,
@ -181,31 +179,6 @@ impl<'a> CrateReader<'a> {
}
}
// Dup of the above, but for the hir
fn extract_crate_info_hir(&self, i: &hir::Item) -> Option<CrateInfo> {
match i.node {
hir::ItemExternCrate(ref path_opt) => {
debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
i.name, path_opt);
let name = match *path_opt {
Some(name) => {
validate_crate_name(Some(self.sess), &name.as_str(),
Some(i.span));
name.to_string()
}
None => i.name.to_string(),
};
Some(CrateInfo {
ident: i.name.to_string(),
name: name,
id: i.id,
should_link: should_link_hir(i),
})
}
_ => None
}
}
fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind)
-> Option<ast::CrateNum> {
let mut ret = None;
@ -776,29 +749,30 @@ impl<'a> CrateReader<'a> {
}
}
impl<'a, 'b> LocalCrateReader<'a, 'b> {
impl<'a> LocalCrateReader<'a> {
pub fn new(sess: &'a Session,
cstore: &'a CStore,
map: &'a hir_map::Map<'b>,
defs: &'a RefCell<hir_map::Definitions>,
krate: &'a ast::Crate,
local_crate_name: &str)
-> LocalCrateReader<'a, 'b> {
-> LocalCrateReader<'a> {
LocalCrateReader {
sess: sess,
cstore: cstore,
creader: CrateReader::new(sess, cstore, local_crate_name),
ast_map: map,
krate: krate,
defintions: defs,
}
}
// Traverses an AST, reading all the information about use'd crates and
// extern libraries necessary for later resolving, typechecking, linking,
// etc.
pub fn read_crates(&mut self) {
let _task = self.ast_map.dep_graph.in_task(DepNode::CrateReader);
let krate = self.ast_map.krate();
pub fn read_crates(&mut self, dep_graph: &DepGraph) {
let _task = dep_graph.in_task(DepNode::CrateReader);
self.process_crate(krate);
krate.visit_all_items(self);
self.process_crate(self.krate);
visit::walk_crate(self, self.krate);
self.creader.inject_allocator_crate();
if log_enabled!(log::INFO) {
@ -811,34 +785,34 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
self.creader.register_statically_included_foreign_items();
}
fn process_crate(&self, c: &hir::Crate) {
fn process_crate(&self, c: &ast::Crate) {
for a in c.attrs.iter().filter(|m| m.name() == "link_args") {
match a.value_str() {
Some(ref linkarg) => self.cstore.add_used_link_args(&linkarg),
None => { /* fallthrough */ }
if let Some(ref linkarg) = a.value_str() {
self.cstore.add_used_link_args(&linkarg);
}
}
}
fn process_item(&mut self, i: &hir::Item) {
fn process_item(&mut self, i: &ast::Item) {
match i.node {
hir::ItemExternCrate(_) => {
if !should_link_hir(i) {
ast::ItemKind::ExternCrate(_) => {
if !should_link(i) {
return;
}
match self.creader.extract_crate_info_hir(i) {
match self.creader.extract_crate_info(i) {
Some(info) => {
let (cnum, _, _) = self.creader.resolve_crate(&None,
&info.ident,
&info.name,
None,
i.span,
PathKind::Crate,
true);
let def_id = self.ast_map.local_def_id(i.id);
&info.ident,
&info.name,
None,
i.span,
PathKind::Crate,
true);
let len = self.ast_map.def_path(def_id).data.len();
let defs = self.defintions.borrow();
let def_id = defs.opt_local_def_id(i.id).unwrap();
let len = defs.def_path(def_id.index).data.len();
self.creader.update_extern_crate(cnum,
ExternCrate {
@ -852,12 +826,12 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
None => ()
}
}
hir::ItemForeignMod(ref fm) => self.process_foreign_mod(i, fm),
ast::ItemKind::ForeignMod(ref fm) => self.process_foreign_mod(i, fm),
_ => { }
}
}
fn process_foreign_mod(&mut self, i: &hir::Item, fm: &hir::ForeignMod) {
fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
if fm.abi == Abi::Rust || fm.abi == Abi::RustIntrinsic || fm.abi == Abi::PlatformIntrinsic {
return;
}

View File

@ -17,10 +17,10 @@ use super::data::*;
use super::dump::Dump;
use super::span_utils::SpanUtils;
pub struct CsvDumper<'a, 'b, W: 'b> {
pub struct CsvDumper<'tcx, 'b, W: 'b> {
output: &'b mut W,
dump_spans: bool,
span: SpanUtils<'a>
span: SpanUtils<'tcx>
}
impl<'a, 'b, W: Write> CsvDumper<'a, 'b, W> {

View File

@ -42,7 +42,7 @@ use syntax::visit::{self, Visitor};
use syntax::print::pprust::{path_to_string, ty_to_string};
use syntax::ptr::P;
use rustc::hir::lowering::{lower_expr, LoweringContext};
use rustc::hir::lowering::lower_expr;
use super::{escape, generated_code, SaveContext, PathCollector};
use super::data::*;
@ -60,12 +60,12 @@ macro_rules! down_cast_data {
};
}
pub struct DumpVisitor<'l, 'tcx: 'l, D: 'l> {
pub struct DumpVisitor<'l, 'tcx: 'l, 'll, D: 'll> {
save_ctxt: SaveContext<'l, 'tcx>,
sess: &'l Session,
tcx: &'l TyCtxt<'tcx>,
analysis: &'l ty::CrateAnalysis<'l>,
dumper: &'l mut D,
dumper: &'ll mut D,
span: SpanUtils<'l>,
@ -77,22 +77,19 @@ pub struct DumpVisitor<'l, 'tcx: 'l, D: 'l> {
// one macro use per unique callsite span.
mac_defs: HashSet<Span>,
mac_uses: HashSet<Span>,
}
impl <'l, 'tcx, D> DumpVisitor<'l, 'tcx, D>
where D: Dump
{
impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
pub fn new(tcx: &'l TyCtxt<'tcx>,
lcx: &'l LoweringContext<'l>,
save_ctxt: SaveContext<'l, 'tcx>,
analysis: &'l ty::CrateAnalysis<'l>,
dumper: &'l mut D)
-> DumpVisitor<'l, 'tcx, D> {
dumper: &'ll mut D)
-> DumpVisitor<'l, 'tcx, 'll, D> {
let span_utils = SpanUtils::new(&tcx.sess);
DumpVisitor {
sess: &tcx.sess,
tcx: tcx,
save_ctxt: SaveContext::from_span_utils(tcx, lcx, span_utils.clone()),
save_ctxt: save_ctxt,
analysis: analysis,
dumper: dumper,
span: span_utils.clone(),
@ -103,7 +100,7 @@ where D: Dump
}
fn nest<F>(&mut self, scope_id: NodeId, f: F)
where F: FnOnce(&mut DumpVisitor<'l, 'tcx, D>)
where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, D>)
{
let parent_scope = self.cur_scope;
self.cur_scope = scope_id;
@ -982,7 +979,7 @@ where D: Dump
}
}
impl<'l, 'tcx, 'v, D: Dump + 'l> Visitor<'v> for DumpVisitor<'l, 'tcx, D> {
impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, 'll, D> {
fn visit_item(&mut self, item: &ast::Item) {
use syntax::ast::ItemKind::*;
self.process_macro_use(item.span, item.id);

View File

@ -73,7 +73,7 @@ pub mod recorder {
pub struct SaveContext<'l, 'tcx: 'l> {
tcx: &'l TyCtxt<'tcx>,
lcx: &'l lowering::LoweringContext<'l>,
span_utils: SpanUtils<'l>,
span_utils: SpanUtils<'tcx>,
}
macro_rules! option_try(
@ -90,7 +90,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
pub fn from_span_utils(tcx: &'l TyCtxt<'tcx>,
lcx: &'l lowering::LoweringContext<'l>,
span_utils: SpanUtils<'l>)
span_utils: SpanUtils<'tcx>)
-> SaveContext<'l, 'tcx> {
SaveContext {
tcx: tcx,
@ -680,7 +680,7 @@ impl<'v> Visitor<'v> for PathCollector {
pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>,
lcx: &'l lowering::LoweringContext<'l>,
krate: &ast::Crate,
analysis: &ty::CrateAnalysis,
analysis: &'l ty::CrateAnalysis<'l>,
cratename: &str,
odir: Option<&Path>) {
let _ignore = tcx.dep_graph.in_ignore();
@ -726,9 +726,10 @@ pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>,
});
root_path.pop();
let utils = SpanUtils::new(&tcx.sess);
let utils: SpanUtils<'tcx> = SpanUtils::new(&tcx.sess);
let save_ctxt = SaveContext::new(tcx, lcx);
let mut dumper = CsvDumper::new(&mut output_file, utils);
let mut visitor = DumpVisitor::new(tcx, lcx, analysis, &mut dumper);
let mut visitor = DumpVisitor::new(tcx, save_ctxt, analysis, &mut dumper);
// FIXME: we don't write anything!
visitor.dump_crate_info(cratename, krate);

View File

@ -26,6 +26,8 @@ use syntax::parse::token::{keywords, Token};
#[derive(Clone)]
pub struct SpanUtils<'a> {
pub sess: &'a Session,
// FIXME given that we clone SpanUtils all over the place, this err_count is
// probably useless and any logic relying on it is bogus.
pub err_count: Cell<isize>,
}

View File

@ -22,6 +22,7 @@ use rustc_trans::back::link;
use rustc_resolve as resolve;
use rustc::hir::lowering::{lower_crate, LoweringContext};
use rustc_metadata::cstore::CStore;
use rustc_metadata::creader::LocalCrateReader;
use syntax::{ast, codemap, errors};
use syntax::errors::emitter::ColorConfig;
@ -151,14 +152,18 @@ pub fn run_core(search_paths: SearchPaths,
.expect("phase_2_configure_and_expand aborted in rustdoc!");
let krate = driver::assign_node_ids(&sess, krate);
let dep_graph = DepGraph::new(false);
let defs = &RefCell::new(hir_map::collect_definitions(&krate));
LocalCrateReader::new(&sess, &cstore, &defs, &krate, &name).read_crates(&dep_graph);
let lcx = LoweringContext::new(&sess, Some(&krate), defs);
// Lower ast -> hir.
let lcx = LoweringContext::new(&sess, Some(&krate));
let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), DepGraph::new(false));
let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph);
let arenas = ty::CtxtArenas::new();
let hir_map = driver::make_map(&sess, &mut hir_forest);
let hir_map = hir_map::map_crate(&mut hir_forest, defs);
abort_on_err(driver::phase_3_run_analysis_passes(&sess,
&cstore,
hir_map,
&arenas,
&name,

View File

@ -94,15 +94,17 @@ pub fn run(input: &str,
"rustdoc-test", None)
.expect("phase_2_configure_and_expand aborted in rustdoc!");
let krate = driver::assign_node_ids(&sess, krate);
let lcx = LoweringContext::new(&sess, Some(&krate));
let dep_graph = DepGraph::new(false);
let defs = &RefCell::new(hir_map::collect_definitions(&krate));
let lcx = LoweringContext::new(&sess, Some(&krate), defs);
let krate = lower_crate(&lcx, &krate);
let opts = scrape_test_config(&krate);
let dep_graph = DepGraph::new(false);
let _ignore = dep_graph.in_ignore();
let mut forest = hir_map::Forest::new(krate, dep_graph.clone());
let map = hir_map::map_crate(&mut forest);
let map = hir_map::map_crate(&mut forest, defs);
let ctx = core::DocContext {
map: &map,

View File

@ -20,6 +20,7 @@ extern crate rustc_metadata;
extern crate rustc_resolve;
#[macro_use] extern crate syntax;
use std::cell::RefCell;
use std::ffi::{CStr, CString};
use std::mem::transmute;
use std::path::PathBuf;
@ -35,6 +36,7 @@ use rustc::session::build_session;
use rustc_driver::{driver, abort_on_err};
use rustc::hir::lowering::{lower_crate, LoweringContext};
use rustc_resolve::MakeGlobMap;
use rustc_metadata::creader::LocalCrateReader;
use rustc_metadata::cstore::CStore;
use libc::c_void;
@ -237,15 +239,17 @@ fn compile_program(input: &str, sysroot: PathBuf)
let krate = driver::phase_2_configure_and_expand(&sess, &cstore, krate, &id, None)
.expect("phase_2 returned `None`");
let krate = driver::assign_node_ids(&sess, krate);
let lcx = LoweringContext::new(&sess, Some(&krate));
let dep_graph = DepGraph::new(sess.opts.build_dep_graph());
let krate = driver::assign_node_ids(&sess, krate);
let defs = RefCell::new(ast_map::collect_definitions(&krate));
LocalCrateReader::new(&sess, &cstore, &defs, &krate, &id).read_crates(&dep_graph);
let lcx = LoweringContext::new(&sess, Some(&krate), &defs);
let mut hir_forest = ast_map::Forest::new(lower_crate(&lcx, &krate), dep_graph);
let arenas = ty::CtxtArenas::new();
let ast_map = driver::make_map(&sess, &mut hir_forest);
let ast_map = ast_map::map_crate(&mut hir_forest, &defs);
abort_on_err(driver::phase_3_run_analysis_passes(
&sess, &cstore, ast_map, &arenas, &id,
&sess, ast_map, &arenas, &id,
MakeGlobMap::No, |tcx, mir_map, analysis, _| {
let trans = driver::phase_4_translate_to_llvm(tcx, mir_map.unwrap(), analysis);