From 76eaed44d9a4556bbbd603200d805175c8ebf18e Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 10 Jun 2015 02:40:45 +0300 Subject: syntax: move ast_map to librustc. --- src/librustc/ast_map/blocks.rs | 254 ++++++ src/librustc/ast_map/mod.rs | 1023 +++++++++++++++++++++++ src/librustc/lib.rs | 2 + src/librustc/metadata/csearch.rs | 2 +- src/librustc/metadata/decoder.rs | 2 +- src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/astencode.rs | 3 +- src/librustc/middle/cfg/graphviz.rs | 2 +- src/librustc/middle/check_static_recursion.rs | 4 +- src/librustc/middle/const_eval.rs | 5 +- src/librustc/middle/dead.rs | 3 +- src/librustc/middle/entry.rs | 2 +- src/librustc/middle/infer/error_reporting.rs | 2 +- src/librustc/middle/intrinsicck.rs | 2 +- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/reachable.rs | 2 +- src/librustc/middle/region.rs | 2 +- src/librustc/middle/ty.rs | 2 +- src/librustc/util/ppaux.rs | 2 +- src/librustc_borrowck/borrowck/mod.rs | 4 +- src/librustc_driver/driver.rs | 2 +- src/librustc_driver/pretty.rs | 2 +- src/librustc_driver/test.rs | 3 +- src/librustc_lint/builtin.rs | 3 +- src/librustc_privacy/lib.rs | 3 +- src/librustc_resolve/lib.rs | 2 +- src/librustc_trans/back/link.rs | 4 +- src/librustc_trans/save/dump_csv.rs | 2 +- src/librustc_trans/trans/base.rs | 3 +- src/librustc_trans/trans/callee.rs | 2 +- src/librustc_trans/trans/common.rs | 2 +- src/librustc_trans/trans/debuginfo/metadata.rs | 3 +- src/librustc_trans/trans/debuginfo/mod.rs | 3 +- src/librustc_trans/trans/debuginfo/namespace.rs | 3 +- src/librustc_trans/trans/foreign.rs | 3 +- src/librustc_trans/trans/meth.rs | 3 +- src/librustc_trans/trans/monomorphize.rs | 2 +- src/librustc_typeck/coherence/mod.rs | 3 +- src/librustc_typeck/collect.rs | 2 +- src/librustc_typeck/lib.rs | 3 +- src/librustc_typeck/variance.rs | 2 +- src/librustdoc/core.rs | 3 +- src/librustdoc/visit_ast.rs | 2 +- src/libsyntax/ast_map/blocks.rs | 255 ------ src/libsyntax/ast_map/mod.rs | 1023 ----------------------- src/libsyntax/lib.rs | 2 - src/test/run-make/execution-engine/test.rs | 2 +- 47 files changed, 1338 insertions(+), 1326 deletions(-) create mode 100644 src/librustc/ast_map/blocks.rs create mode 100644 src/librustc/ast_map/mod.rs delete mode 100644 src/libsyntax/ast_map/blocks.rs delete mode 100644 src/libsyntax/ast_map/mod.rs diff --git a/src/librustc/ast_map/blocks.rs b/src/librustc/ast_map/blocks.rs new file mode 100644 index 00000000000..6c9ed29768f --- /dev/null +++ b/src/librustc/ast_map/blocks.rs @@ -0,0 +1,254 @@ +// Copyright 2014 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. + +//! This module provides a simplified abstraction for working with +//! code blocks identified by their integer node-id. In particular, +//! it captures a common set of attributes that all "function-like +//! things" (represented by `FnLike` instances) share. For example, +//! all `FnLike` instances have a type signature (be it explicit or +//! inferred). And all `FnLike` instances have a body, i.e. the code +//! that is run when the function-like thing it represents is invoked. +//! +//! With the above abstraction in place, one can treat the program +//! text as a collection of blocks of code (and most such blocks are +//! nested within a uniquely determined `FnLike`), and users can ask +//! for the `Code` associated with a particular NodeId. + +pub use self::Code::*; + +use ast_map::{self, Node}; +use syntax::abi; +use syntax::ast::{Block, FnDecl, NodeId}; +use syntax::ast; +use syntax::codemap::Span; +use syntax::visit; + +/// An FnLikeNode is a Node that is like a fn, in that it has a decl +/// and a body (as well as a NodeId, a span, etc). +/// +/// More specifically, it is one of either: +/// - A function item, +/// - A closure expr (i.e. an ExprClosure), or +/// - The default implementation for a trait method. +/// +/// To construct one, use the `Code::from_node` function. +#[derive(Copy, Clone)] +pub struct FnLikeNode<'a> { node: ast_map::Node<'a> } + +/// MaybeFnLike wraps a method that indicates if an object +/// corresponds to some FnLikeNode. +pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; } + +/// Components shared by fn-like things (fn items, methods, closures). +pub struct FnParts<'a> { + pub decl: &'a FnDecl, + pub body: &'a Block, + pub kind: visit::FnKind<'a>, + pub span: Span, + pub id: NodeId, +} + +impl MaybeFnLike for ast::Item { + fn is_fn_like(&self) -> bool { + match self.node { ast::ItemFn(..) => true, _ => false, } + } +} + +impl MaybeFnLike for ast::TraitItem { + fn is_fn_like(&self) -> bool { + match self.node { ast::MethodTraitItem(_, Some(_)) => true, _ => false, } + } +} + +impl MaybeFnLike for ast::Expr { + fn is_fn_like(&self) -> bool { + match self.node { + ast::ExprClosure(..) => true, + _ => false, + } + } +} + +/// Carries either an FnLikeNode or a Block, as these are the two +/// constructs that correspond to "code" (as in, something from which +/// we can construct a control-flow graph). +#[derive(Copy, Clone)] +pub enum Code<'a> { + FnLikeCode(FnLikeNode<'a>), + BlockCode(&'a Block), +} + +impl<'a> Code<'a> { + pub fn id(&self) -> ast::NodeId { + match *self { + FnLikeCode(node) => node.id(), + BlockCode(block) => block.id, + } + } + + /// Attempts to construct a Code from presumed FnLike or Block node input. + pub fn from_node(node: Node) -> Option { + if let ast_map::NodeBlock(block) = node { + Some(BlockCode(block)) + } else { + FnLikeNode::from_node(node).map(|fn_like| FnLikeCode(fn_like)) + } + } +} + +/// These are all the components one can extract from a fn item for +/// use when implementing FnLikeNode operations. +struct ItemFnParts<'a> { + ident: ast::Ident, + decl: &'a ast::FnDecl, + unsafety: ast::Unsafety, + constness: ast::Constness, + abi: abi::Abi, + vis: ast::Visibility, + generics: &'a ast::Generics, + body: &'a Block, + id: ast::NodeId, + span: Span +} + +/// These are all the components one can extract from a closure expr +/// for use when implementing FnLikeNode operations. +struct ClosureParts<'a> { + decl: &'a FnDecl, + body: &'a Block, + id: NodeId, + span: Span +} + +impl<'a> ClosureParts<'a> { + fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span) -> ClosureParts<'a> { + ClosureParts { decl: d, body: b, id: id, span: s } + } +} + +impl<'a> FnLikeNode<'a> { + /// Attempts to construct a FnLikeNode from presumed FnLike node input. + pub fn from_node(node: Node) -> Option { + let fn_like = match node { + ast_map::NodeItem(item) => item.is_fn_like(), + ast_map::NodeTraitItem(tm) => tm.is_fn_like(), + ast_map::NodeImplItem(_) => true, + ast_map::NodeExpr(e) => e.is_fn_like(), + _ => false + }; + if fn_like { + Some(FnLikeNode { + node: node + }) + } else { + None + } + } + + pub fn to_fn_parts(self) -> FnParts<'a> { + FnParts { + decl: self.decl(), + body: self.body(), + kind: self.kind(), + span: self.span(), + id: self.id(), + } + } + + pub fn body(self) -> &'a Block { + self.handle(|i: ItemFnParts<'a>| &*i.body, + |_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _| body, + |c: ClosureParts<'a>| c.body) + } + + pub fn decl(self) -> &'a FnDecl { + self.handle(|i: ItemFnParts<'a>| &*i.decl, + |_, _, sig: &'a ast::MethodSig, _, _, _| &sig.decl, + |c: ClosureParts<'a>| c.decl) + } + + pub fn span(self) -> Span { + self.handle(|i: ItemFnParts| i.span, + |_, _, _: &'a ast::MethodSig, _, _, span| span, + |c: ClosureParts| c.span) + } + + pub fn id(self) -> NodeId { + self.handle(|i: ItemFnParts| i.id, + |id, _, _: &'a ast::MethodSig, _, _, _| id, + |c: ClosureParts| c.id) + } + + pub fn kind(self) -> visit::FnKind<'a> { + let item = |p: ItemFnParts<'a>| -> visit::FnKind<'a> { + visit::FkItemFn(p.ident, p.generics, p.unsafety, p.constness, p.abi, p.vis) + }; + let closure = |_: ClosureParts| { + visit::FkFnBlock + }; + let method = |_, ident, sig: &'a ast::MethodSig, vis, _, _| { + visit::FkMethod(ident, sig, vis) + }; + self.handle(item, method, closure) + } + + fn handle(self, item_fn: I, method: M, closure: C) -> A where + I: FnOnce(ItemFnParts<'a>) -> A, + M: FnOnce(NodeId, + ast::Ident, + &'a ast::MethodSig, + Option, + &'a ast::Block, + Span) + -> A, + C: FnOnce(ClosureParts<'a>) -> A, + { + match self.node { + ast_map::NodeItem(i) => match i.node { + ast::ItemFn(ref decl, unsafety, constness, abi, ref generics, ref block) => + item_fn(ItemFnParts { + id: i.id, + ident: i.ident, + decl: &**decl, + unsafety: unsafety, + body: &**block, + generics: generics, + abi: abi, + vis: i.vis, + constness: constness, + span: i.span + }), + _ => panic!("item FnLikeNode that is not fn-like"), + }, + ast_map::NodeTraitItem(ti) => match ti.node { + ast::MethodTraitItem(ref sig, Some(ref body)) => { + method(ti.id, ti.ident, sig, None, body, ti.span) + } + _ => panic!("trait method FnLikeNode that is not fn-like"), + }, + ast_map::NodeImplItem(ii) => { + match ii.node { + ast::MethodImplItem(ref sig, ref body) => { + method(ii.id, ii.ident, sig, Some(ii.vis), body, ii.span) + } + _ => { + panic!("impl method FnLikeNode that is not fn-like") + } + } + } + ast_map::NodeExpr(e) => match e.node { + ast::ExprClosure(_, ref decl, ref block) => + closure(ClosureParts::new(&**decl, &**block, e.id, e.span)), + _ => panic!("expr FnLikeNode that is not fn-like"), + }, + _ => panic!("other FnLikeNode that is not fn-like"), + } + } +} diff --git a/src/librustc/ast_map/mod.rs b/src/librustc/ast_map/mod.rs new file mode 100644 index 00000000000..94b740da608 --- /dev/null +++ b/src/librustc/ast_map/mod.rs @@ -0,0 +1,1023 @@ +// Copyright 2012-2013 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. + +pub use self::Node::*; +pub use self::PathElem::*; +use self::MapEntry::*; + +use syntax::abi; +use syntax::ast::*; +use syntax::ast_util; +use syntax::codemap::{DUMMY_SP, Span, Spanned}; +use syntax::fold::Folder; +use syntax::parse::token; +use syntax::print::pprust; +use syntax::visit::{self, Visitor}; + +use arena::TypedArena; +use std::cell::RefCell; +use std::fmt; +use std::io; +use std::iter::{self, repeat}; +use std::mem; +use std::slice; + +pub mod blocks; + +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum PathElem { + PathMod(Name), + PathName(Name) +} + +impl PathElem { + pub fn name(&self) -> Name { + match *self { + PathMod(name) | PathName(name) => name + } + } +} + +impl fmt::Display for PathElem { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let slot = token::get_name(self.name()); + write!(f, "{}", slot) + } +} + +#[derive(Clone)] +pub struct LinkedPathNode<'a> { + node: PathElem, + next: LinkedPath<'a>, +} + +#[derive(Copy, Clone)] +pub struct LinkedPath<'a>(Option<&'a LinkedPathNode<'a>>); + +impl<'a> LinkedPath<'a> { + pub fn empty() -> LinkedPath<'a> { + LinkedPath(None) + } + + pub fn from(node: &'a LinkedPathNode) -> LinkedPath<'a> { + LinkedPath(Some(node)) + } +} + +impl<'a> Iterator for LinkedPath<'a> { + type Item = PathElem; + + fn next(&mut self) -> Option { + match self.0 { + Some(node) => { + *self = node.next; + Some(node.node) + } + None => None + } + } +} + +/// The type of the iterator used by with_path. +pub type PathElems<'a, 'b> = iter::Chain>, LinkedPath<'b>>; + +pub fn path_to_string>(path: PI) -> String { + let itr = token::get_ident_interner(); + + path.fold(String::new(), |mut s, e| { + let e = itr.get(e.name()); + if !s.is_empty() { + s.push_str("::"); + } + s.push_str(&e[..]); + s + }) +} + +#[derive(Copy, Clone, Debug)] +pub enum Node<'ast> { + NodeItem(&'ast Item), + NodeForeignItem(&'ast ForeignItem), + NodeTraitItem(&'ast TraitItem), + NodeImplItem(&'ast ImplItem), + NodeVariant(&'ast Variant), + NodeExpr(&'ast Expr), + NodeStmt(&'ast Stmt), + NodeArg(&'ast Pat), + NodeLocal(&'ast Pat), + NodePat(&'ast Pat), + NodeBlock(&'ast Block), + + /// NodeStructCtor represents a tuple struct. + NodeStructCtor(&'ast StructDef), + + NodeLifetime(&'ast Lifetime), +} + +/// Represents an entry and its parent Node ID +/// The odd layout is to bring down the total size. +#[derive(Copy, Debug)] +enum MapEntry<'ast> { + /// Placeholder for holes in the map. + NotPresent, + + /// All the node types, with a parent ID. + EntryItem(NodeId, &'ast Item), + EntryForeignItem(NodeId, &'ast ForeignItem), + EntryTraitItem(NodeId, &'ast TraitItem), + EntryImplItem(NodeId, &'ast ImplItem), + EntryVariant(NodeId, &'ast Variant), + EntryExpr(NodeId, &'ast Expr), + EntryStmt(NodeId, &'ast Stmt), + EntryArg(NodeId, &'ast Pat), + EntryLocal(NodeId, &'ast Pat), + EntryPat(NodeId, &'ast Pat), + EntryBlock(NodeId, &'ast Block), + EntryStructCtor(NodeId, &'ast StructDef), + EntryLifetime(NodeId, &'ast Lifetime), + + /// Roots for node trees. + RootCrate, + RootInlinedParent(&'ast InlinedParent) +} + +impl<'ast> Clone for MapEntry<'ast> { + fn clone(&self) -> MapEntry<'ast> { + *self + } +} + +#[derive(Debug)] +struct InlinedParent { + path: Vec, + ii: InlinedItem +} + +impl<'ast> MapEntry<'ast> { + fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> { + match node { + NodeItem(n) => EntryItem(p, n), + NodeForeignItem(n) => EntryForeignItem(p, n), + NodeTraitItem(n) => EntryTraitItem(p, n), + NodeImplItem(n) => EntryImplItem(p, n), + NodeVariant(n) => EntryVariant(p, n), + NodeExpr(n) => EntryExpr(p, n), + NodeStmt(n) => EntryStmt(p, n), + NodeArg(n) => EntryArg(p, n), + NodeLocal(n) => EntryLocal(p, n), + NodePat(n) => EntryPat(p, n), + NodeBlock(n) => EntryBlock(p, n), + NodeStructCtor(n) => EntryStructCtor(p, n), + NodeLifetime(n) => EntryLifetime(p, n) + } + } + + fn parent(self) -> Option { + Some(match self { + EntryItem(id, _) => id, + EntryForeignItem(id, _) => id, + EntryTraitItem(id, _) => id, + EntryImplItem(id, _) => id, + EntryVariant(id, _) => id, + EntryExpr(id, _) => id, + EntryStmt(id, _) => id, + EntryArg(id, _) => id, + EntryLocal(id, _) => id, + EntryPat(id, _) => id, + EntryBlock(id, _) => id, + EntryStructCtor(id, _) => id, + EntryLifetime(id, _) => id, + _ => return None + }) + } + + fn to_node(self) -> Option> { + Some(match self { + EntryItem(_, n) => NodeItem(n), + EntryForeignItem(_, n) => NodeForeignItem(n), + EntryTraitItem(_, n) => NodeTraitItem(n), + EntryImplItem(_, n) => NodeImplItem(n), + EntryVariant(_, n) => NodeVariant(n), + EntryExpr(_, n) => NodeExpr(n), + EntryStmt(_, n) => NodeStmt(n), + EntryArg(_, n) => NodeArg(n), + EntryLocal(_, n) => NodeLocal(n), + EntryPat(_, n) => NodePat(n), + EntryBlock(_, n) => NodeBlock(n), + EntryStructCtor(_, n) => NodeStructCtor(n), + EntryLifetime(_, n) => NodeLifetime(n), + _ => return None + }) + } +} + +/// Stores a crate and any number of inlined items from other crates. +pub struct Forest { + krate: Crate, + inlined_items: TypedArena +} + +impl Forest { + pub fn new(krate: Crate) -> Forest { + Forest { + krate: krate, + inlined_items: TypedArena::new() + } + } + + pub fn krate<'ast>(&'ast self) -> &'ast Crate { + &self.krate + } +} + +/// Represents a mapping from Node IDs to AST elements and their parent +/// Node IDs +pub struct Map<'ast> { + /// The backing storage for all the AST nodes. + forest: &'ast Forest, + + /// NodeIds are sequential integers from 0, so we can be + /// super-compact by storing them in a vector. Not everything with + /// a NodeId is in the map, but empirically the occupancy is about + /// 75-80%, so there's not too much overhead (certainly less than + /// a hashmap, since they (at the time of writing) have a maximum + /// of 75% occupancy). + /// + /// Also, indexing is pretty quick when you've got a vector and + /// plain old integers. + map: RefCell>> +} + +impl<'ast> Map<'ast> { + fn entry_count(&self) -> usize { + self.map.borrow().len() + } + + fn find_entry(&self, id: NodeId) -> Option> { + self.map.borrow().get(id as usize).cloned() + } + + pub fn krate(&self) -> &'ast Crate { + &self.forest.krate + } + + /// Retrieve the Node corresponding to `id`, panicking if it cannot + /// be found. + pub fn get(&self, id: NodeId) -> Node<'ast> { + match self.find(id) { + Some(node) => node, + None => panic!("couldn't find node id {} in the AST map", id) + } + } + + /// Retrieve the Node corresponding to `id`, returning None if + /// cannot be found. + pub fn find(&self, id: NodeId) -> Option> { + self.find_entry(id).and_then(|x| x.to_node()) + } + + /// Retrieve the parent NodeId for `id`, or `id` itself if no + /// parent is registered in this map. + pub fn get_parent(&self, id: NodeId) -> NodeId { + self.find_entry(id).and_then(|x| x.parent()).unwrap_or(id) + } + + pub fn get_parent_did(&self, id: NodeId) -> DefId { + let parent = self.get_parent(id); + match self.find_entry(parent) { + Some(RootInlinedParent(&InlinedParent {ii: IITraitItem(did, _), ..})) => did, + Some(RootInlinedParent(&InlinedParent {ii: IIImplItem(did, _), ..})) => did, + _ => ast_util::local_def(parent) + } + } + + pub fn get_foreign_abi(&self, id: NodeId) -> abi::Abi { + let parent = self.get_parent(id); + let abi = match self.find_entry(parent) { + Some(EntryItem(_, i)) => { + match i.node { + ItemForeignMod(ref nm) => Some(nm.abi), + _ => None + } + } + /// Wrong but OK, because the only inlined foreign items are intrinsics. + Some(RootInlinedParent(_)) => Some(abi::RustIntrinsic), + _ => None + }; + match abi { + Some(abi) => abi, + None => panic!("expected foreign mod or inlined parent, found {}", + self.node_to_string(parent)) + } + } + + pub fn get_foreign_vis(&self, id: NodeId) -> Visibility { + let vis = self.expect_foreign_item(id).vis; + match self.find(self.get_parent(id)) { + Some(NodeItem(i)) => vis.inherit_from(i.vis), + _ => vis + } + } + + pub fn expect_item(&self, id: NodeId) -> &'ast Item { + match self.find(id) { + Some(NodeItem(item)) => item, + _ => panic!("expected item, found {}", self.node_to_string(id)) + } + } + + pub fn expect_struct(&self, id: NodeId) -> &'ast StructDef { + match self.find(id) { + Some(NodeItem(i)) => { + match i.node { + ItemStruct(ref struct_def, _) => &**struct_def, + _ => panic!("struct ID bound to non-struct") + } + } + Some(NodeVariant(variant)) => { + match variant.node.kind { + StructVariantKind(ref struct_def) => &**struct_def, + _ => panic!("struct ID bound to enum variant that isn't struct-like"), + } + } + _ => panic!(format!("expected struct, found {}", self.node_to_string(id))), + } + } + + pub fn expect_variant(&self, id: NodeId) -> &'ast Variant { + match self.find(id) { + Some(NodeVariant(variant)) => variant, + _ => panic!(format!("expected variant, found {}", self.node_to_string(id))), + } + } + + pub fn expect_foreign_item(&self, id: NodeId) -> &'ast ForeignItem { + match self.find(id) { + Some(NodeForeignItem(item)) => item, + _ => panic!("expected foreign item, found {}", self.node_to_string(id)) + } + } + + pub fn expect_expr(&self, id: NodeId) -> &'ast Expr { + match self.find(id) { + Some(NodeExpr(expr)) => expr, + _ => panic!("expected expr, found {}", self.node_to_string(id)) + } + } + + /// returns the name associated with the given NodeId's AST + pub fn get_path_elem(&self, id: NodeId) -> PathElem { + let node = self.get(id); + match node { + NodeItem(item) => { + match item.node { + ItemMod(_) | ItemForeignMod(_) => { + PathMod(item.ident.name) + } + _ => PathName(item.ident.name) + } + } + NodeForeignItem(i) => PathName(i.ident.name), + NodeImplItem(ii) => PathName(ii.ident.name), + NodeTraitItem(ti) => PathName(ti.ident.name), + NodeVariant(v) => PathName(v.node.name.name), + _ => panic!("no path elem for {:?}", node) + } + } + + pub fn with_path(&self, id: NodeId, f: F) -> T where + F: FnOnce(PathElems) -> T, + { + self.with_path_next(id, LinkedPath::empty(), f) + } + + pub fn path_to_string(&self, id: NodeId) -> String { + self.with_path(id, |path| path_to_string(path)) + } + + fn path_to_str_with_ident(&self, id: NodeId, i: Ident) -> String { + self.with_path(id, |path| { + path_to_string(path.chain(Some(PathName(i.name)).into_iter())) + }) + } + + fn with_path_next(&self, id: NodeId, next: LinkedPath, f: F) -> T where + F: FnOnce(PathElems) -> T, + { + let parent = self.get_parent(id); + let parent = match self.find_entry(id) { + Some(EntryForeignItem(..)) | Some(EntryVariant(..)) => { + // Anonymous extern items, enum variants and struct ctors + // go in the parent scope. + self.get_parent(parent) + } + // But tuple struct ctors don't have names, so use the path of its + // parent, the struct item. Similarly with closure expressions. + Some(EntryStructCtor(..)) | Some(EntryExpr(..)) => { + return self.with_path_next(parent, next, f); + } + _ => parent + }; + if parent == id { + match self.find_entry(id) { + Some(RootInlinedParent(data)) => { + f(data.path.iter().cloned().chain(next)) + } + _ => f([].iter().cloned().chain(next)) + } + } else { + self.with_path_next(parent, LinkedPath::from(&LinkedPathNode { + node: self.get_path_elem(id), + next: next + }), f) + } + } + + /// Given a node ID, get a list of of attributes associated with the AST + /// corresponding to the Node ID + pub fn attrs(&self, id: NodeId) -> &'ast [Attribute] { + let attrs = match self.find(id) { + Some(NodeItem(i)) => Some(&i.attrs[..]), + Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]), + Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]), + Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]), + Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]), + // unit/tuple structs take the attributes straight from + // the struct definition. + Some(NodeStructCtor(_)) => { + return self.attrs(self.get_parent(id)); + } + _ => None + }; + attrs.unwrap_or(&[]) + } + + /// Returns an iterator that yields the node id's with paths that + /// match `parts`. (Requires `parts` is non-empty.) + /// + /// For example, if given `parts` equal to `["bar", "quux"]`, then + /// the iterator will produce node id's for items with paths + /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and + /// any other such items it can find in the map. + pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String]) + -> NodesMatchingSuffix<'a, 'ast> { + NodesMatchingSuffix { + map: self, + item_name: parts.last().unwrap(), + in_which: &parts[..parts.len() - 1], + idx: 0, + } + } + + pub fn opt_span(&self, id: NodeId) -> Option { + let sp = match self.find(id) { + Some(NodeItem(item)) => item.span, + Some(NodeForeignItem(foreign_item)) => foreign_item.span, + Some(NodeTraitItem(trait_method)) => trait_method.span, + Some(NodeImplItem(ref impl_item)) => impl_item.span, + Some(NodeVariant(variant)) => variant.span, + Some(NodeExpr(expr)) => expr.span, + Some(NodeStmt(stmt)) => stmt.span, + Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span, + Some(NodePat(pat)) => pat.span, + Some(NodeBlock(block)) => block.span, + Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span, + _ => return None, + }; + Some(sp) + } + + pub fn span(&self, id: NodeId) -> Span { + self.opt_span(id) + .unwrap_or_else(|| panic!("AstMap.span: could not find span for id {:?}", id)) + } + + pub fn def_id_span(&self, def_id: DefId, fallback: Span) -> Span { + if def_id.krate == LOCAL_CRATE { + self.opt_span(def_id.node).unwrap_or(fallback) + } else { + fallback + } + } + + pub fn node_to_string(&self, id: NodeId) -> String { + node_id_to_string(self, id, true) + } + + pub fn node_to_user_string(&self, id: NodeId) -> String { + node_id_to_string(self, id, false) + } +} + +pub struct NodesMatchingSuffix<'a, 'ast:'a> { + map: &'a Map<'ast>, + item_name: &'a String, + in_which: &'a [String], + idx: NodeId, +} + +impl<'a, 'ast> NodesMatchingSuffix<'a, 'ast> { + /// Returns true only if some suffix of the module path for parent + /// matches `self.in_which`. + /// + /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`; + /// returns true if parent's path ends with the suffix + /// `x_0::x_1::...::x_k`. + fn suffix_matches(&self, parent: NodeId) -> bool { + let mut cursor = parent; + for part in self.in_which.iter().rev() { + let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) { + None => return false, + Some((node_id, name)) => (node_id, name), + }; + if &part[..] != mod_name.as_str() { + return false; + } + cursor = self.map.get_parent(mod_id); + } + return true; + + // Finds the first mod in parent chain for `id`, along with + // that mod's name. + // + // If `id` itself is a mod named `m` with parent `p`, then + // returns `Some(id, m, p)`. If `id` has no mod in its parent + // chain, then returns `None`. + fn find_first_mod_parent<'a>(map: &'a Map, mut id: NodeId) -> Option<(NodeId, Name)> { + loop { + match map.find(id) { + None => return None, + Some(NodeItem(item)) if item_is_mod(&*item) => + return Some((id, item.ident.name)), + _ => {} + } + let parent = map.get_parent(id); + if parent == id { return None } + id = parent; + } + + fn item_is_mod(item: &Item) -> bool { + match item.node { + ItemMod(_) => true, + _ => false, + } + } + } + } + + // We are looking at some node `n` with a given name and parent + // id; do their names match what I am seeking? + fn matches_names(&self, parent_of_n: NodeId, name: Name) -> bool { + name.as_str() == &self.item_name[..] && + self.suffix_matches(parent_of_n) + } +} + +impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> { + type Item = NodeId; + + fn next(&mut self) -> Option { + loop { + let idx = self.idx; + if idx as usize >= self.map.entry_count() { + return None; + } + self.idx += 1; + let (p, name) = match self.map.find_entry(idx) { + Some(EntryItem(p, n)) => (p, n.name()), + Some(EntryForeignItem(p, n))=> (p, n.name()), + Some(EntryTraitItem(p, n)) => (p, n.name()), + Some(EntryImplItem(p, n)) => (p, n.name()), + Some(EntryVariant(p, n)) => (p, n.name()), + _ => continue, + }; + if self.matches_names(p, name) { + return Some(idx) + } + } + } +} + +trait Named { + fn name(&self) -> Name; +} + +impl Named for Spanned { fn name(&self) -> Name { self.node.name() } } + +impl Named for Item { fn name(&self) -> Name { self.ident.name } } +impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } } +impl Named for Variant_ { fn name(&self) -> Name { self.name.name } } +impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } } +impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } } + +pub trait FoldOps { + fn new_id(&self, id: NodeId) -> NodeId { + id + } + fn new_def_id(&self, def_id: DefId) -> DefId { + def_id + } + fn new_span(&self, span: Span) -> Span { + span + } +} + +/// A Folder that updates IDs and Span's according to fold_ops. +struct IdAndSpanUpdater { + fold_ops: F +} + +impl Folder for IdAndSpanUpdater { + fn new_id(&mut self, id: NodeId) -> NodeId { + self.fold_ops.new_id(id) + } + + fn new_span(&mut self, span: Span) -> Span { + self.fold_ops.new_span(span) + } +} + +/// A Visitor that walks over an AST and collects Node's into an AST Map. +struct NodeCollector<'ast> { + map: Vec>, + /// The node in which we are currently mapping (an item or a method). + parent: NodeId +} + +impl<'ast> NodeCollector<'ast> { + fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) { + debug!("ast_map: {:?} => {:?}", id, entry); + let len = self.map.len(); + if id as usize >= len { + self.map.extend(repeat(NotPresent).take(id as usize - len + 1)); + } + self.map[id as usize] = entry; + } + + fn insert(&mut self, id: NodeId, node: Node<'ast>) { + let entry = MapEntry::from_node(self.parent, node); + self.insert_entry(id, entry); + } + + fn visit_fn_decl(&mut self, decl: &'ast FnDecl) { + for a in &decl.inputs { + self.insert(a.id, NodeArg(&*a.pat)); + } + } +} + +impl<'ast> Visitor<'ast> for NodeCollector<'ast> { + fn visit_item(&mut self, i: &'ast Item) { + self.insert(i.id, NodeItem(i)); + let parent = self.parent; + self.parent = i.id; + match i.node { + ItemImpl(_, _, _, _, _, ref impl_items) => { + for ii in impl_items { + self.insert(ii.id, NodeImplItem(ii)); + } + } + ItemEnum(ref enum_definition, _) => { + for v in &enum_definition.variants { + self.insert(v.node.id, NodeVariant(&**v)); + } + } + ItemForeignMod(ref nm) => { + for nitem in &nm.items { + self.insert(nitem.id, NodeForeignItem(&**nitem)); + } + } + ItemStruct(ref struct_def, _) => { + // If this is a tuple-like struct, register the constructor. + match struct_def.ctor_id { + Some(ctor_id) => { + self.insert(ctor_id, NodeStructCtor(&**struct_def)); + } + None => {} + } + } + ItemTrait(_, _, ref bounds, ref trait_items) => { + for b in &**bounds { + if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b { + self.insert(t.trait_ref.ref_id, NodeItem(i)); + } + } + + for ti in trait_items { + self.insert(ti.id, NodeTraitItem(ti)); + } + } + ItemUse(ref view_path) => { + match view_path.node { + ViewPathList(_, ref paths) => { + for path in paths { + self.insert(path.node.id(), NodeItem(i)); + } + } + _ => () + } + } + _ => {} + } + visit::walk_item(self, i); + self.parent = parent; + } + + fn visit_trait_item(&mut self, ti: &'ast TraitItem) { + let parent = self.parent; + self.parent = ti.id; + visit::walk_trait_item(self, ti); + self.parent = parent; + } + + fn visit_impl_item(&mut self, ii: &'ast ImplItem) { + let parent = self.parent; + self.parent = ii.id; + visit::walk_impl_item(self, ii); + self.parent = parent; + } + + fn visit_pat(&mut self, pat: &'ast Pat) { + self.insert(pat.id, match pat.node { + // Note: this is at least *potentially* a pattern... + PatIdent(..) => NodeLocal(pat), + _ => NodePat(pat) + }); + visit::walk_pat(self, pat); + } + + fn visit_expr(&mut self, expr: &'ast Expr) { + self.insert(expr.id, NodeExpr(expr)); + visit::walk_expr(self, expr); + } + + fn visit_stmt(&mut self, stmt: &'ast Stmt) { + self.insert(ast_util::stmt_id(stmt), NodeStmt(stmt)); + visit::walk_stmt(self, stmt); + } + + fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl, + b: &'ast Block, s: Span, _: NodeId) { + self.visit_fn_decl(fd); + visit::walk_fn(self, fk, fd, b, s); + } + + fn visit_ty(&mut self, ty: &'ast Ty) { + match ty.node { + TyBareFn(ref fd) => { + self.visit_fn_decl(&*fd.decl); + } + _ => {} + } + visit::walk_ty(self, ty); + } + + fn visit_block(&mut self, block: &'ast Block) { + self.insert(block.id, NodeBlock(block)); + visit::walk_block(self, block); + } + + fn visit_lifetime_ref(&mut self, lifetime: &'ast Lifetime) { + self.insert(lifetime.id, NodeLifetime(lifetime)); + } + + fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) { + self.visit_lifetime_ref(&def.lifetime); + } +} + +pub fn map_crate<'ast, F: FoldOps>(forest: &'ast mut Forest, fold_ops: F) -> Map<'ast> { + // Replace the crate with an empty one to take it out. + let krate = mem::replace(&mut forest.krate, Crate { + module: Mod { + inner: DUMMY_SP, + items: vec![], + }, + attrs: vec![], + config: vec![], + exported_macros: vec![], + span: DUMMY_SP + }); + forest.krate = IdAndSpanUpdater { fold_ops: fold_ops }.fold_crate(krate); + + let mut collector = NodeCollector { + map: vec![], + parent: CRATE_NODE_ID + }; + collector.insert_entry(CRATE_NODE_ID, RootCrate); + visit::walk_crate(&mut collector, &forest.krate); + let map = collector.map; + + if log_enabled!(::log::DEBUG) { + // This only makes sense for ordered stores; note the + // enumerate to count the number of entries. + let (entries_less_1, _) = map.iter().filter(|&x| { + match *x { + NotPresent => false, + _ => true + } + }).enumerate().last().expect("AST map was empty after folding?"); + + let entries = entries_less_1 + 1; + let vector_length = map.len(); + debug!("The AST map has {} entries with a maximum of {}: occupancy {:.1}%", + entries, vector_length, (entries as f64 / vector_length as f64) * 100.); + } + + Map { + forest: forest, + map: RefCell::new(map) + } +} + +/// Used for items loaded from external crate that are being inlined into this +/// crate. The `path` should be the path to the item but should not include +/// the item itself. +pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>, + path: Vec, + ii: InlinedItem, + fold_ops: F) + -> &'ast InlinedItem { + let mut fld = IdAndSpanUpdater { fold_ops: fold_ops }; + let ii = match ii { + IIItem(i) => IIItem(fld.fold_item(i).expect_one("expected one item")), + IITraitItem(d, ti) => { + IITraitItem(fld.fold_ops.new_def_id(d), + fld.fold_trait_item(ti).expect_one("expected one trait item")) + } + IIImplItem(d, ii) => { + IIImplItem(fld.fold_ops.new_def_id(d), + fld.fold_impl_item(ii).expect_one("expected one impl item")) + } + IIForeign(i) => IIForeign(fld.fold_foreign_item(i)) + }; + + let ii_parent = map.forest.inlined_items.alloc(InlinedParent { + path: path, + ii: ii + }); + + let mut collector = NodeCollector { + map: mem::replace(&mut *map.map.borrow_mut(), vec![]), + parent: fld.new_id(DUMMY_NODE_ID) + }; + let ii_parent_id = collector.parent; + collector.insert_entry(ii_parent_id, RootInlinedParent(ii_parent)); + visit::walk_inlined_item(&mut collector, &ii_parent.ii); + + // Methods get added to the AST map when their impl is visited. Since we + // don't decode and instantiate the impl, but just the method, we have to + // add it to the table now. Likewise with foreign items. + match ii_parent.ii { + IIItem(_) => {} + IITraitItem(_, ref ti) => { + collector.insert(ti.id, NodeTraitItem(ti)); + } + IIImplItem(_, ref ii) => { + collector.insert(ii.id, NodeImplItem(ii)); + } + IIForeign(ref i) => { + collector.insert(i.id, NodeForeignItem(i)); + } + } + *map.map.borrow_mut() = collector.map; + &ii_parent.ii +} + +pub trait NodePrinter { + fn print_node(&mut self, node: &Node) -> io::Result<()>; +} + +impl<'a> NodePrinter for pprust::State<'a> { + fn print_node(&mut self, node: &Node) -> io::Result<()> { + match *node { + NodeItem(a) => self.print_item(&*a), + NodeForeignItem(a) => self.print_foreign_item(&*a), + NodeTraitItem(a) => self.print_trait_item(a), + NodeImplItem(a) => self.print_impl_item(a), + NodeVariant(a) => self.print_variant(&*a), + NodeExpr(a) => self.print_expr(&*a), + NodeStmt(a) => self.print_stmt(&*a), + NodePat(a) => self.print_pat(&*a), + NodeBlock(a) => self.print_block(&*a), + NodeLifetime(a) => self.print_lifetime(&*a), + + // these cases do not carry enough information in the + // ast_map to reconstruct their full structure for pretty + // printing. + NodeLocal(_) => panic!("cannot print isolated Local"), + NodeArg(_) => panic!("cannot print isolated Arg"), + NodeStructCtor(_) => panic!("cannot print isolated StructCtor"), + } + } +} + +fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { + let id_str = format!(" (id={})", id); + let id_str = if include_id { &id_str[..] } else { "" }; + + match map.find(id) { + Some(NodeItem(item)) => { + let path_str = map.path_to_str_with_ident(id, item.ident); + let item_str = match item.node { + ItemExternCrate(..) => "extern crate", + ItemUse(..) => "use", + ItemStatic(..) => "static", + ItemConst(..) => "const", + ItemFn(..) => "fn", + ItemMod(..) => "mod", + ItemForeignMod(..) => "foreign mod", + ItemTy(..) => "ty", + ItemEnum(..) => "enum", + ItemStruct(..) => "struct", + ItemTrait(..) => "trait", + ItemImpl(..) => "impl", + ItemDefaultImpl(..) => "default impl", + ItemMac(..) => "macro" + }; + format!("{} {}{}", item_str, path_str, id_str) + } + Some(NodeForeignItem(item)) => { + let path_str = map.path_to_str_with_ident(id, item.ident); + format!("foreign item {}{}", path_str, id_str) + } + Some(NodeImplItem(ii)) => { + match ii.node { + ConstImplItem(..) => { + format!("assoc const {} in {}{}", + token::get_ident(ii.ident), + map.path_to_string(id), + id_str) + } + MethodImplItem(..) => { + format!("method {} in {}{}", + token::get_ident(ii.ident), + map.path_to_string(id), id_str) + } + TypeImplItem(_) => { + format!("assoc type {} in {}{}", + token::get_ident(ii.ident), + map.path_to_string(id), + id_str) + } + MacImplItem(ref mac) => { + format!("method macro {}{}", + pprust::mac_to_string(mac), id_str) + } + } + } + Some(NodeTraitItem(ti)) => { + let kind = match ti.node { + ConstTraitItem(..) => "assoc constant", + MethodTraitItem(..) => "trait method", + TypeTraitItem(..) => "assoc type", + }; + + format!("{} {} in {}{}", + kind, + token::get_ident(ti.ident), + map.path_to_string(id), + id_str) + } + Some(NodeVariant(ref variant)) => { + format!("variant {} in {}{}", + token::get_ident(variant.node.name), + map.path_to_string(id), id_str) + } + Some(NodeExpr(ref expr)) => { + format!("expr {}{}", pprust::expr_to_string(&**expr), id_str) + } + Some(NodeStmt(ref stmt)) => { + format!("stmt {}{}", pprust::stmt_to_string(&**stmt), id_str) + } + Some(NodeArg(ref pat)) => { + format!("arg {}{}", pprust::pat_to_string(&**pat), id_str) + } + Some(NodeLocal(ref pat)) => { + format!("local {}{}", pprust::pat_to_string(&**pat), id_str) + } + Some(NodePat(ref pat)) => { + format!("pat {}{}", pprust::pat_to_string(&**pat), id_str) + } + Some(NodeBlock(ref block)) => { + format!("block {}{}", pprust::block_to_string(&**block), id_str) + } + Some(NodeStructCtor(_)) => { + format!("struct_ctor {}{}", map.path_to_string(id), id_str) + } + Some(NodeLifetime(ref l)) => { + format!("lifetime {}{}", + pprust::lifetime_to_string(&**l), id_str) + } + None => { + format!("unknown node{}", id_str) + } + } +} diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 4a715ca621c..8b46e2fe2e9 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -92,6 +92,8 @@ pub mod back { pub use rustc_back::x86_64; } +pub mod ast_map; + pub mod middle { pub mod astconv_util; pub mod astencode; diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 081c035b595..4e0cf7b0e4c 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -10,6 +10,7 @@ // Searching for information from the cstore +use ast_map; use metadata::common::*; use metadata::cstore; use metadata::decoder; @@ -20,7 +21,6 @@ use rbml; use rbml::reader; use std::rc::Rc; use syntax::ast; -use syntax::ast_map; use syntax::attr; use syntax::attr::AttrMetaMethods; use syntax::diagnostic::expect; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 2a7ec48378a..195d993d14b 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -15,6 +15,7 @@ pub use self::DefLike::*; use self::Family::*; +use ast_map; use back::svh::Svh; use metadata::cstore::crate_metadata; use metadata::common::*; @@ -44,7 +45,6 @@ use std::str; use rbml::reader; use rbml; use serialize::Decodable; -use syntax::ast_map; use syntax::attr; use syntax::parse::token::{IdentInterner, special_idents}; use syntax::parse::token; diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 8eefb4d5011..9d213c8cfe8 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -15,6 +15,7 @@ pub use self::InlinedItemRef::*; +use ast_map::{self, LinkedPath, PathElem, PathElems}; use back::svh::Svh; use session::config; use metadata::common::*; @@ -34,7 +35,6 @@ use std::io::prelude::*; use std::io::{Cursor, SeekFrom}; use syntax::abi; use syntax::ast::{self, DefId, NodeId}; -use syntax::ast_map::{self, LinkedPath, PathElem, PathElems}; use syntax::ast_util::*; use syntax::ast_util; use syntax::attr; diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 3242dafbd1c..d96ea12bcef 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -12,6 +12,7 @@ // FIXME: remove this after snapshot, and Results are handled #![allow(unused_must_use)] +use ast_map; use metadata::common as c; use metadata::cstore as cstore; use session::Session; @@ -32,7 +33,7 @@ use middle::subst::VecPerParamSpace; use middle::ty::{self, Ty, MethodCall, MethodCallee, MethodOrigin}; use util::ppaux::ty_to_string; -use syntax::{ast, ast_map, ast_util, codemap, fold}; +use syntax::{ast, ast_util, codemap, fold}; use syntax::codemap::Span; use syntax::fold::Folder; use syntax::parse::token; diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs index 3a6966ab112..76050671cc4 100644 --- a/src/librustc/middle/cfg/graphviz.rs +++ b/src/librustc/middle/cfg/graphviz.rs @@ -17,8 +17,8 @@ use std::borrow::IntoCow; use graphviz as dot; use syntax::ast; -use syntax::ast_map; +use ast_map; use middle::cfg; pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode); diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs index a521c4531c9..41beabc9588 100644 --- a/src/librustc/middle/check_static_recursion.rs +++ b/src/librustc/middle/check_static_recursion.rs @@ -11,11 +11,11 @@ // This compiler pass detects static items that refer to themselves // recursively. +use ast_map; use session::Session; use middle::def::{DefStatic, DefConst, DefAssociatedConst, DefMap}; -use syntax::ast; -use syntax::{ast_util, ast_map}; +use syntax::{ast, ast_util}; use syntax::codemap::Span; use syntax::visit::Visitor; use syntax::visit; diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 188bf4bf77b..e35a71be123 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -15,6 +15,8 @@ pub use self::const_val::*; use self::ErrKind::*; +use ast_map; +use ast_map::blocks::FnLikeNode; use metadata::csearch; use middle::{astencode, def, infer, subst, traits}; use middle::pat_util::def_to_path; @@ -24,13 +26,12 @@ use util::num::ToPrimitive; use util::ppaux::Repr; use syntax::ast::{self, Expr}; -use syntax::ast_map::blocks::FnLikeNode; use syntax::ast_util; use syntax::codemap::Span; use syntax::feature_gate; use syntax::parse::token::InternedString; use syntax::ptr::P; -use syntax::{ast_map, codemap, visit}; +use syntax::{codemap, visit}; use std::borrow::{Cow, IntoCow}; use std::num::wrapping::OverflowingOps; diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 1aa2ca9115d..c06de29450b 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -12,12 +12,13 @@ // closely. The idea is that all reachable symbols are live, codes called // from live codes are live, and everything else is dead. +use ast_map; use middle::{def, pat_util, privacy, ty}; use lint; use util::nodemap::NodeSet; use std::collections::HashSet; -use syntax::{ast, ast_map, codemap}; +use syntax::{ast, codemap}; use syntax::ast_util::{local_def, is_local}; use syntax::attr::{self, AttrMetaMethods}; use syntax::visit::{self, Visitor}; diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 0ce9db1c80f..c6e5b654f9a 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -9,9 +9,9 @@ // except according to those terms. +use ast_map; use session::{config, Session}; use syntax::ast::{Name, NodeId, Item, ItemFn}; -use syntax::ast_map; use syntax::attr; use syntax::codemap::Span; use syntax::parse::token; diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index c9a863c0963..37cc5d34299 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -72,6 +72,7 @@ use super::region_inference::ProcessedErrors; use super::region_inference::SameRegions; use std::collections::HashSet; +use ast_map; use middle::def; use middle::infer; use middle::subst; @@ -81,7 +82,6 @@ use std::cell::{Cell, RefCell}; use std::char::from_u32; use std::string::String; use syntax::ast; -use syntax::ast_map; use syntax::ast_util::name_to_dummy_lifetime; use syntax::owned_slice::OwnedSlice; use syntax::codemap; diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index b67f0434918..d05954c44d5 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use ast_map::NodeForeignItem; use metadata::csearch; use middle::def::DefFn; use middle::subst::{Subst, Substs, EnumeratedItems}; @@ -18,7 +19,6 @@ use util::ppaux::Repr; use syntax::abi::RustIntrinsic; use syntax::ast::DefId; use syntax::ast; -use syntax::ast_map::NodeForeignItem; use syntax::codemap::Span; use syntax::parse::token; use syntax::visit::Visitor; diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 3fff1504993..5c6e955992d 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -73,6 +73,7 @@ pub use self::categorization::*; use self::Aliasability::*; +use ast_map; use middle::check_const; use middle::def; use middle::region; @@ -82,7 +83,6 @@ use util::ppaux::{Repr, UserString}; use syntax::ast::{MutImmutable, MutMutable}; use syntax::ast; -use syntax::ast_map; use syntax::codemap::Span; use syntax::print::pprust; use syntax::parse::token; diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index f374c9749c2..378b3c41128 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -15,6 +15,7 @@ // makes all other generics or inline functions that it references // reachable as well. +use ast_map; use middle::def; use middle::ty; use middle::privacy; @@ -24,7 +25,6 @@ use util::nodemap::NodeSet; use std::collections::HashSet; use syntax::abi; use syntax::ast; -use syntax::ast_map; use syntax::ast_util::is_local; use syntax::attr; use syntax::visit::Visitor; diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 2c510b5f1d3..2a033d36a47 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -16,6 +16,7 @@ //! Most of the documentation on regions can be found in //! `middle/typeck/infer/region_inference.rs` +use ast_map; use session::Session; use middle::ty::{self, Ty}; use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap}; @@ -25,7 +26,6 @@ use syntax::codemap::{self, Span}; use syntax::{ast, visit}; use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local}; use syntax::ast_util::stmt_id; -use syntax::ast_map; use syntax::ptr::P; use syntax::visit::{Visitor, FnKind}; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 0b014c9e6a2..035b4a467bc 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -35,6 +35,7 @@ pub use self::IntVarValue::*; pub use self::MethodOrigin::*; pub use self::CopyImplementationError::*; +use ast_map::{self, LinkedPath}; use back::svh::Svh; use session::Session; use lint; @@ -91,7 +92,6 @@ use syntax::parse::token::{self, InternedString, special_idents}; use syntax::print::pprust; use syntax::ptr::P; use syntax::ast; -use syntax::ast_map::{self, LinkedPath}; pub type Disr = u64; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index acbd09f671b..958bb26e1f5 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -9,6 +9,7 @@ // except according to those terms. +use ast_map; use middle::def; use middle::region; use middle::subst::{VecPerParamSpace,Subst}; @@ -31,7 +32,6 @@ use std::collections::hash_state::HashState; use std::hash::Hash; use std::rc::Rc; use syntax::abi; -use syntax::ast_map; use syntax::codemap::{Span, Pos}; use syntax::parse::token; use syntax::print::pprust; diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 472aff6625b..d7046171616 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -20,6 +20,8 @@ pub use self::MovedValueUseKind::*; use self::InteriorKind::*; +use rustc::ast_map; +use rustc::ast_map::blocks::{FnLikeNode, FnParts}; use rustc::middle::cfg; use rustc::middle::dataflow::DataFlowContext; use rustc::middle::dataflow::BitwiseOperator; @@ -35,8 +37,6 @@ use std::mem; use std::rc::Rc; use std::string::String; use syntax::ast; -use syntax::ast_map; -use syntax::ast_map::blocks::{FnLikeNode, FnParts}; use syntax::ast_util; use syntax::codemap::Span; use syntax::parse::token; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 13dec30e0a0..aa57a280157 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -11,6 +11,7 @@ use rustc::session::Session; use rustc::session::config::{self, Input, OutputFilenames}; use rustc::session::search_paths::PathKind; +use rustc::ast_map; use rustc::lint; use rustc::metadata; use rustc::metadata::creader::CrateReader; @@ -37,7 +38,6 @@ use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::ast_map; use syntax::attr; use syntax::attr::AttrMetaMethods; use syntax::diagnostics; diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index b8032bda8d0..c98052825e1 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -19,6 +19,7 @@ use rustc_trans::back::link; use driver; +use rustc::ast_map::{self, blocks, NodePrinter}; use rustc::middle::ty; use rustc::middle::cfg; use rustc::middle::cfg::graphviz::LabelledCFG; @@ -30,7 +31,6 @@ use rustc_borrowck::graphviz as borrowck_dot; use rustc_resolve as resolve; use syntax::ast; -use syntax::ast_map::{self, blocks, NodePrinter}; use syntax::codemap; use syntax::fold::{self, Folder}; use syntax::print::{pp, pprust}; diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index b53f2b1dcfa..fd7f549a879 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -29,8 +29,9 @@ use rustc_typeck::middle::infer::lub::Lub; use rustc_typeck::middle::infer::glb::Glb; use rustc_typeck::middle::infer::sub::Sub; use rustc_typeck::util::ppaux::{ty_to_string, Repr, UserString}; +use rustc::ast_map; use rustc::session::{self,config}; -use syntax::{abi, ast, ast_map}; +use syntax::{abi, ast}; use syntax::codemap; use syntax::codemap::{Span, CodeMap, DUMMY_SP}; use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note, Help}; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 4678b5335ea..7b78ab44454 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -35,6 +35,7 @@ use middle::ty::{self, Ty}; use middle::{def, pat_util, stability}; use middle::const_eval::{eval_const_expr_partial, const_int, const_uint}; use middle::cfg; +use rustc::ast_map; use util::ppaux::ty_to_string; use util::nodemap::{FnvHashMap, NodeSet}; use lint::{Level, Context, LintPass, LintArray, Lint}; @@ -44,7 +45,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::{cmp, slice}; use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64}; -use syntax::{abi, ast, ast_map}; +use syntax::{abi, ast}; use syntax::ast_util::{self, is_shift_binop, local_def}; use syntax::attr::{self, AttrMetaMethods}; use syntax::codemap::{self, Span}; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 36d175fb59b..67bc4a8a7f3 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -33,6 +33,7 @@ use self::FieldName::*; use std::mem::replace; +use rustc::ast_map; use rustc::metadata::csearch; use rustc::middle::def; use rustc::middle::privacy::ImportUse::*; @@ -46,7 +47,7 @@ use rustc::middle::ty::MethodTraitObject; use rustc::middle::ty::{self, Ty}; use rustc::util::nodemap::{NodeMap, NodeSet}; -use syntax::{ast, ast_map}; +use syntax::ast; use syntax::ast_util::{is_local, local_def}; use syntax::codemap::Span; use syntax::parse::token; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ba8680a35cb..d55024aefb1 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -49,6 +49,7 @@ use self::ParentLink::*; use self::ModuleKind::*; use self::FallbackChecks::*; +use rustc::ast_map; use rustc::session::Session; use rustc::lint; use rustc::metadata::csearch; @@ -80,7 +81,6 @@ use syntax::ast::{TyPath, TyPtr}; use syntax::ast::{TyRptr, TyStr, TyUs, TyU8, TyU16, TyU32, TyU64, TyUint}; use syntax::ast::TypeImplItem; use syntax::ast; -use syntax::ast_map; use syntax::ast_util::{local_def, walk_pat}; use syntax::attr::AttrMetaMethods; use syntax::ext::mtwt; diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 3de91d58740..5ab7895940f 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -21,8 +21,9 @@ use session::Session; use metadata::common::LinkMeta; use metadata::{encoder, cstore, filesearch, csearch, creader}; use metadata::filesearch::FileDoesntMatch; -use trans::{CrateContext, CrateTranslation, gensym_name}; use middle::ty::{self, Ty}; +use rustc::ast_map::{PathElem, PathElems, PathName}; +use trans::{CrateContext, CrateTranslation, gensym_name}; use util::common::time; use util::ppaux; use util::sha2::{Digest, Sha256}; @@ -38,7 +39,6 @@ use std::str; use flate; use serialize::hex::ToHex; use syntax::ast; -use syntax::ast_map::{PathElem, PathElems, PathName}; use syntax::attr::AttrMetaMethods; use syntax::codemap::Span; use syntax::parse::token; diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index 30c72d68fb0..f36f35acbd4 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -34,6 +34,7 @@ use session::Session; use middle::def; use middle::ty::{self, Ty}; +use rustc::ast_map::NodeItem; use std::cell::Cell; use std::fs::File; @@ -41,7 +42,6 @@ use std::path::Path; use syntax::ast_util; use syntax::ast::{self, NodeId, DefId}; -use syntax::ast_map::NodeItem; use syntax::codemap::*; use syntax::parse::token::{self, get_ident, keywords}; use syntax::owned_slice::OwnedSlice; diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 390c0b035fd..1ead6f89f61 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -41,6 +41,7 @@ use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; use middle::weak_lang_items; use middle::subst::Substs; use middle::ty::{self, Ty, ClosureTyper, type_is_simd, simd_size}; +use rustc::ast_map; use session::config::{self, NoDebugInfo}; use session::Session; use trans::_match; @@ -99,7 +100,7 @@ use syntax::codemap::Span; use syntax::parse::token::InternedString; use syntax::visit::Visitor; use syntax::visit; -use syntax::{ast, ast_util, ast_map}; +use syntax::{ast, ast_util}; thread_local! { static TASK_LOCAL_INSN_KEY: RefCell>> = { diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 31c9b60f478..e619ce2f262 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -53,12 +53,12 @@ use trans::type_::Type; use trans::type_of; use middle::ty::{self, Ty}; use middle::ty::MethodCall; +use rustc::ast_map; use util::ppaux::Repr; use util::ppaux::ty_to_string; use syntax::abi as synabi; use syntax::ast; -use syntax::ast_map; use syntax::ptr::P; #[derive(Copy, Clone)] diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 6259f8fe1cc..021321cacaf 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -40,6 +40,7 @@ use middle::traits; use middle::ty::{self, HasProjectionTypes, Ty}; use middle::ty_fold; use middle::ty_fold::{TypeFolder, TypeFoldable}; +use rustc::ast_map::{PathElem, PathName}; use util::ppaux::Repr; use util::nodemap::{FnvHashMap, NodeMap}; @@ -50,7 +51,6 @@ use std::cell::{Cell, RefCell}; use std::result::Result as StdResult; use std::vec::Vec; use syntax::ast; -use syntax::ast_map::{PathElem, PathName}; use syntax::codemap::{DUMMY_SP, Span}; use syntax::parse::token::InternedString; use syntax::parse::token; diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs index ab86cd7cdde..5117cda1f6b 100644 --- a/src/librustc_trans/trans/debuginfo/metadata.rs +++ b/src/librustc_trans/trans/debuginfo/metadata.rs @@ -26,6 +26,7 @@ use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType}; use metadata::csearch; use middle::pat_util; use middle::subst::{self, Substs}; +use rustc::ast_map; use trans::{type_of, adt, machine, monomorphize}; use trans::common::{self, CrateContext, FunctionContext, NormalizingClosureTyper, Block}; use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef}; @@ -43,7 +44,7 @@ use std::ptr; use std::rc::Rc; use syntax::util::interner::Interner; use syntax::codemap::Span; -use syntax::{ast, codemap, ast_util, ast_map}; +use syntax::{ast, codemap, ast_util}; use syntax::parse::token::{self, special_idents}; diff --git a/src/librustc_trans/trans/debuginfo/mod.rs b/src/librustc_trans/trans/debuginfo/mod.rs index 71312bb60a2..7210c35e0e0 100644 --- a/src/librustc_trans/trans/debuginfo/mod.rs +++ b/src/librustc_trans/trans/debuginfo/mod.rs @@ -26,6 +26,7 @@ use llvm::{ModuleRef, ContextRef, ValueRef}; use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIDescriptor, FlagPrototyped}; use middle::subst::{self, Substs}; +use rustc::ast_map; use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block}; use trans; use trans::monomorphize; @@ -39,7 +40,7 @@ use std::ffi::CString; use std::ptr; use std::rc::Rc; use syntax::codemap::{Span, Pos}; -use syntax::{ast, codemap, ast_util, ast_map}; +use syntax::{ast, codemap, ast_util}; use syntax::parse::token::{self, special_idents}; pub mod gdb; diff --git a/src/librustc_trans/trans/debuginfo/namespace.rs b/src/librustc_trans/trans/debuginfo/namespace.rs index a41a62dcd4c..e6fe674f220 100644 --- a/src/librustc_trans/trans/debuginfo/namespace.rs +++ b/src/librustc_trans/trans/debuginfo/namespace.rs @@ -14,13 +14,14 @@ use super::utils::{DIB, debug_context}; use llvm; use llvm::debuginfo::DIScope; +use rustc::ast_map; use trans::common::CrateContext; use middle::ty::{self, ClosureTyper}; use std::ffi::CString; use std::ptr; use std::rc::{Rc, Weak}; -use syntax::{ast, ast_map}; +use syntax::ast; use syntax::parse::token; pub struct NamespaceTreeNode { diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 95c93d76585..583beb19ff7 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -13,6 +13,7 @@ use back::link; use llvm::{ValueRef, CallConv, get_param}; use llvm; use middle::weak_lang_items; +use rustc::ast_map; use trans::attributes; use trans::base::{llvm_linkage_by_name, push_ctxt}; use trans::base; @@ -37,7 +38,7 @@ use syntax::codemap::Span; use syntax::parse::token::{InternedString, special_idents}; use syntax::parse::token; use syntax::ast; -use syntax::{attr, ast_map}; +use syntax::attr; use syntax::print::pprust; use util::ppaux::Repr; diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index feb2b879183..1934b72eca3 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -18,6 +18,7 @@ use middle::subst::VecPerParamSpace; use middle::subst; use middle::traits; use middle::ty::ClosureTyper; +use rustc::ast_map; use trans::base::*; use trans::build::*; use trans::callee::*; @@ -42,7 +43,7 @@ use util::ppaux::Repr; use syntax::abi::{Rust, RustCall}; use syntax::parse::token; -use syntax::{ast, ast_map, attr, visit}; +use syntax::{ast, attr, visit}; use syntax::codemap::DUMMY_SP; use syntax::ptr::P; diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index 3d74cf46e6e..b736ec3ccf4 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -17,6 +17,7 @@ use middle::subst; use middle::subst::{Subst, Substs}; use middle::traits; use middle::ty_fold::{TypeFolder, TypeFoldable}; +use rustc::ast_map; use trans::attributes; use trans::base::{trans_enum_variant, push_ctxt, get_item_val}; use trans::base::trans_fn; @@ -29,7 +30,6 @@ use util::ppaux::Repr; use syntax::abi; use syntax::ast; -use syntax::ast_map; use syntax::ast_util::local_def; use syntax::attr; use syntax::codemap::DUMMY_SP; diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 212423d16d4..083039a468a 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -32,14 +32,13 @@ use middle::ty; use middle::free_region::FreeRegionMap; use CrateCtxt; use middle::infer::{self, InferCtxt, new_infer_ctxt}; +use rustc::ast_map::{self, NodeItem}; use std::cell::RefCell; use std::rc::Rc; use syntax::ast::{Crate, DefId}; use syntax::ast::{Item, ItemImpl}; use syntax::ast::{LOCAL_CRATE}; use syntax::ast; -use syntax::ast_map::NodeItem; -use syntax::ast_map; use syntax::ast_util::local_def; use syntax::codemap::Span; use syntax::parse::token; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index be2774f46d9..610c429b1fb 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -77,6 +77,7 @@ use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme}; use middle::ty_fold::{self, TypeFolder, TypeFoldable}; use middle::infer; use rscope::*; +use rustc::ast_map; use util::common::{ErrorReported, memoized}; use util::nodemap::{FnvHashMap, FnvHashSet}; use util::ppaux; @@ -89,7 +90,6 @@ use std::rc::Rc; use syntax::abi; use syntax::ast; -use syntax::ast_map; use syntax::ast_util::local_def; use syntax::codemap::Span; use syntax::parse::token::special_idents; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index ed398c2cded..8d7ecca5ddd 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -101,6 +101,7 @@ use middle::def; use middle::infer; use middle::subst; use middle::ty::{self, Ty}; +use rustc::ast_map; use session::config; use util::common::time; use util::ppaux::Repr; @@ -108,7 +109,7 @@ use util::ppaux; use syntax::codemap::Span; use syntax::print::pprust::*; -use syntax::{ast, ast_map, abi}; +use syntax::{ast, abi}; use syntax::ast_util::local_def; use std::cell::RefCell; diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index 7c062d354d3..75f8f7aa81e 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -270,10 +270,10 @@ use middle::resolve_lifetime as rl; use middle::subst; use middle::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace}; use middle::ty::{self, Ty}; +use rustc::ast_map; use std::fmt; use std::rc::Rc; use syntax::ast; -use syntax::ast_map; use syntax::ast_util; use syntax::visit; use syntax::visit::Visitor; diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index f7757b9fee7..3183307250c 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -14,11 +14,12 @@ use rustc_driver::driver; use rustc::session::{self, config}; use rustc::session::config::UnstableFeatures; use rustc::middle::{privacy, ty}; +use rustc::ast_map; use rustc::lint; use rustc_trans::back::link; use rustc_resolve as resolve; -use syntax::{ast, ast_map, codemap, diagnostic}; +use syntax::{ast, codemap, diagnostic}; use std::cell::{RefCell, Cell}; use std::collections::{HashMap, HashSet}; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index e0a462dd437..ff058fa908d 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -17,11 +17,11 @@ use std::mem; use syntax::abi; use syntax::ast; use syntax::ast_util; -use syntax::ast_map; use syntax::attr; use syntax::attr::AttrMetaMethods; use syntax::codemap::Span; +use rustc::ast_map; use rustc::middle::stability; use core; diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs deleted file mode 100644 index 99686d54ce5..00000000000 --- a/src/libsyntax/ast_map/blocks.rs +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2014 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. - -//! This module provides a simplified abstraction for working with -//! code blocks identified by their integer node-id. In particular, -//! it captures a common set of attributes that all "function-like -//! things" (represented by `FnLike` instances) share. For example, -//! all `FnLike` instances have a type signature (be it explicit or -//! inferred). And all `FnLike` instances have a body, i.e. the code -//! that is run when the function-like thing it represents is invoked. -//! -//! With the above abstraction in place, one can treat the program -//! text as a collection of blocks of code (and most such blocks are -//! nested within a uniquely determined `FnLike`), and users can ask -//! for the `Code` associated with a particular NodeId. - -pub use self::Code::*; - -use abi; -use ast::{Block, FnDecl, NodeId}; -use ast; -use ast_map::Node; -use ast_map; -use codemap::Span; -use visit; - -/// An FnLikeNode is a Node that is like a fn, in that it has a decl -/// and a body (as well as a NodeId, a span, etc). -/// -/// More specifically, it is one of either: -/// - A function item, -/// - A closure expr (i.e. an ExprClosure), or -/// - The default implementation for a trait method. -/// -/// To construct one, use the `Code::from_node` function. -#[derive(Copy, Clone)] -pub struct FnLikeNode<'a> { node: ast_map::Node<'a> } - -/// MaybeFnLike wraps a method that indicates if an object -/// corresponds to some FnLikeNode. -pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; } - -/// Components shared by fn-like things (fn items, methods, closures). -pub struct FnParts<'a> { - pub decl: &'a FnDecl, - pub body: &'a Block, - pub kind: visit::FnKind<'a>, - pub span: Span, - pub id: NodeId, -} - -impl MaybeFnLike for ast::Item { - fn is_fn_like(&self) -> bool { - match self.node { ast::ItemFn(..) => true, _ => false, } - } -} - -impl MaybeFnLike for ast::TraitItem { - fn is_fn_like(&self) -> bool { - match self.node { ast::MethodTraitItem(_, Some(_)) => true, _ => false, } - } -} - -impl MaybeFnLike for ast::Expr { - fn is_fn_like(&self) -> bool { - match self.node { - ast::ExprClosure(..) => true, - _ => false, - } - } -} - -/// Carries either an FnLikeNode or a Block, as these are the two -/// constructs that correspond to "code" (as in, something from which -/// we can construct a control-flow graph). -#[derive(Copy, Clone)] -pub enum Code<'a> { - FnLikeCode(FnLikeNode<'a>), - BlockCode(&'a Block), -} - -impl<'a> Code<'a> { - pub fn id(&self) -> ast::NodeId { - match *self { - FnLikeCode(node) => node.id(), - BlockCode(block) => block.id, - } - } - - /// Attempts to construct a Code from presumed FnLike or Block node input. - pub fn from_node(node: Node) -> Option { - if let ast_map::NodeBlock(block) = node { - Some(BlockCode(block)) - } else { - FnLikeNode::from_node(node).map(|fn_like| FnLikeCode(fn_like)) - } - } -} - -/// These are all the components one can extract from a fn item for -/// use when implementing FnLikeNode operations. -struct ItemFnParts<'a> { - ident: ast::Ident, - decl: &'a ast::FnDecl, - unsafety: ast::Unsafety, - constness: ast::Constness, - abi: abi::Abi, - vis: ast::Visibility, - generics: &'a ast::Generics, - body: &'a Block, - id: ast::NodeId, - span: Span -} - -/// These are all the components one can extract from a closure expr -/// for use when implementing FnLikeNode operations. -struct ClosureParts<'a> { - decl: &'a FnDecl, - body: &'a Block, - id: NodeId, - span: Span -} - -impl<'a> ClosureParts<'a> { - fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span) -> ClosureParts<'a> { - ClosureParts { decl: d, body: b, id: id, span: s } - } -} - -impl<'a> FnLikeNode<'a> { - /// Attempts to construct a FnLikeNode from presumed FnLike node input. - pub fn from_node(node: Node) -> Option { - let fn_like = match node { - ast_map::NodeItem(item) => item.is_fn_like(), - ast_map::NodeTraitItem(tm) => tm.is_fn_like(), - ast_map::NodeImplItem(_) => true, - ast_map::NodeExpr(e) => e.is_fn_like(), - _ => false - }; - if fn_like { - Some(FnLikeNode { - node: node - }) - } else { - None - } - } - - pub fn to_fn_parts(self) -> FnParts<'a> { - FnParts { - decl: self.decl(), - body: self.body(), - kind: self.kind(), - span: self.span(), - id: self.id(), - } - } - - pub fn body(self) -> &'a Block { - self.handle(|i: ItemFnParts<'a>| &*i.body, - |_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _| body, - |c: ClosureParts<'a>| c.body) - } - - pub fn decl(self) -> &'a FnDecl { - self.handle(|i: ItemFnParts<'a>| &*i.decl, - |_, _, sig: &'a ast::MethodSig, _, _, _| &sig.decl, - |c: ClosureParts<'a>| c.decl) - } - - pub fn span(self) -> Span { - self.handle(|i: ItemFnParts| i.span, - |_, _, _: &'a ast::MethodSig, _, _, span| span, - |c: ClosureParts| c.span) - } - - pub fn id(self) -> NodeId { - self.handle(|i: ItemFnParts| i.id, - |id, _, _: &'a ast::MethodSig, _, _, _| id, - |c: ClosureParts| c.id) - } - - pub fn kind(self) -> visit::FnKind<'a> { - let item = |p: ItemFnParts<'a>| -> visit::FnKind<'a> { - visit::FkItemFn(p.ident, p.generics, p.unsafety, p.constness, p.abi, p.vis) - }; - let closure = |_: ClosureParts| { - visit::FkFnBlock - }; - let method = |_, ident, sig: &'a ast::MethodSig, vis, _, _| { - visit::FkMethod(ident, sig, vis) - }; - self.handle(item, method, closure) - } - - fn handle(self, item_fn: I, method: M, closure: C) -> A where - I: FnOnce(ItemFnParts<'a>) -> A, - M: FnOnce(NodeId, - ast::Ident, - &'a ast::MethodSig, - Option, - &'a ast::Block, - Span) - -> A, - C: FnOnce(ClosureParts<'a>) -> A, - { - match self.node { - ast_map::NodeItem(i) => match i.node { - ast::ItemFn(ref decl, unsafety, constness, abi, ref generics, ref block) => - item_fn(ItemFnParts { - id: i.id, - ident: i.ident, - decl: &**decl, - unsafety: unsafety, - body: &**block, - generics: generics, - abi: abi, - vis: i.vis, - constness: constness, - span: i.span - }), - _ => panic!("item FnLikeNode that is not fn-like"), - }, - ast_map::NodeTraitItem(ti) => match ti.node { - ast::MethodTraitItem(ref sig, Some(ref body)) => { - method(ti.id, ti.ident, sig, None, body, ti.span) - } - _ => panic!("trait method FnLikeNode that is not fn-like"), - }, - ast_map::NodeImplItem(ii) => { - match ii.node { - ast::MethodImplItem(ref sig, ref body) => { - method(ii.id, ii.ident, sig, Some(ii.vis), body, ii.span) - } - _ => { - panic!("impl method FnLikeNode that is not fn-like") - } - } - } - ast_map::NodeExpr(e) => match e.node { - ast::ExprClosure(_, ref decl, ref block) => - closure(ClosureParts::new(&**decl, &**block, e.id, e.span)), - _ => panic!("expr FnLikeNode that is not fn-like"), - }, - _ => panic!("other FnLikeNode that is not fn-like"), - } - } -} diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs deleted file mode 100644 index ce6c33c6ab6..00000000000 --- a/src/libsyntax/ast_map/mod.rs +++ /dev/null @@ -1,1023 +0,0 @@ -// Copyright 2012-2013 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. - -pub use self::Node::*; -pub use self::PathElem::*; -use self::MapEntry::*; - -use abi; -use ast::*; -use ast_util; -use codemap::{DUMMY_SP, Span, Spanned}; -use fold::Folder; -use parse::token; -use print::pprust; -use visit::{self, Visitor}; - -use arena::TypedArena; -use std::cell::RefCell; -use std::fmt; -use std::io; -use std::iter::{self, repeat}; -use std::mem; -use std::slice; - -pub mod blocks; - -#[derive(Clone, Copy, PartialEq, Debug)] -pub enum PathElem { - PathMod(Name), - PathName(Name) -} - -impl PathElem { - pub fn name(&self) -> Name { - match *self { - PathMod(name) | PathName(name) => name - } - } -} - -impl fmt::Display for PathElem { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let slot = token::get_name(self.name()); - write!(f, "{}", slot) - } -} - -#[derive(Clone)] -pub struct LinkedPathNode<'a> { - node: PathElem, - next: LinkedPath<'a>, -} - -#[derive(Copy, Clone)] -pub struct LinkedPath<'a>(Option<&'a LinkedPathNode<'a>>); - -impl<'a> LinkedPath<'a> { - pub fn empty() -> LinkedPath<'a> { - LinkedPath(None) - } - - pub fn from(node: &'a LinkedPathNode) -> LinkedPath<'a> { - LinkedPath(Some(node)) - } -} - -impl<'a> Iterator for LinkedPath<'a> { - type Item = PathElem; - - fn next(&mut self) -> Option { - match self.0 { - Some(node) => { - *self = node.next; - Some(node.node) - } - None => None - } - } -} - -/// The type of the iterator used by with_path. -pub type PathElems<'a, 'b> = iter::Chain>, LinkedPath<'b>>; - -pub fn path_to_string>(path: PI) -> String { - let itr = token::get_ident_interner(); - - path.fold(String::new(), |mut s, e| { - let e = itr.get(e.name()); - if !s.is_empty() { - s.push_str("::"); - } - s.push_str(&e[..]); - s - }) -} - -#[derive(Copy, Clone, Debug)] -pub enum Node<'ast> { - NodeItem(&'ast Item), - NodeForeignItem(&'ast ForeignItem), - NodeTraitItem(&'ast TraitItem), - NodeImplItem(&'ast ImplItem), - NodeVariant(&'ast Variant), - NodeExpr(&'ast Expr), - NodeStmt(&'ast Stmt), - NodeArg(&'ast Pat), - NodeLocal(&'ast Pat), - NodePat(&'ast Pat), - NodeBlock(&'ast Block), - - /// NodeStructCtor represents a tuple struct. - NodeStructCtor(&'ast StructDef), - - NodeLifetime(&'ast Lifetime), -} - -/// Represents an entry and its parent Node ID -/// The odd layout is to bring down the total size. -#[derive(Copy, Debug)] -enum MapEntry<'ast> { - /// Placeholder for holes in the map. - NotPresent, - - /// All the node types, with a parent ID. - EntryItem(NodeId, &'ast Item), - EntryForeignItem(NodeId, &'ast ForeignItem), - EntryTraitItem(NodeId, &'ast TraitItem), - EntryImplItem(NodeId, &'ast ImplItem), - EntryVariant(NodeId, &'ast Variant), - EntryExpr(NodeId, &'ast Expr), - EntryStmt(NodeId, &'ast Stmt), - EntryArg(NodeId, &'ast Pat), - EntryLocal(NodeId, &'ast Pat), - EntryPat(NodeId, &'ast Pat), - EntryBlock(NodeId, &'ast Block), - EntryStructCtor(NodeId, &'ast StructDef), - EntryLifetime(NodeId, &'ast Lifetime), - - /// Roots for node trees. - RootCrate, - RootInlinedParent(&'ast InlinedParent) -} - -impl<'ast> Clone for MapEntry<'ast> { - fn clone(&self) -> MapEntry<'ast> { - *self - } -} - -#[derive(Debug)] -struct InlinedParent { - path: Vec, - ii: InlinedItem -} - -impl<'ast> MapEntry<'ast> { - fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> { - match node { - NodeItem(n) => EntryItem(p, n), - NodeForeignItem(n) => EntryForeignItem(p, n), - NodeTraitItem(n) => EntryTraitItem(p, n), - NodeImplItem(n) => EntryImplItem(p, n), - NodeVariant(n) => EntryVariant(p, n), - NodeExpr(n) => EntryExpr(p, n), - NodeStmt(n) => EntryStmt(p, n), - NodeArg(n) => EntryArg(p, n), - NodeLocal(n) => EntryLocal(p, n), - NodePat(n) => EntryPat(p, n), - NodeBlock(n) => EntryBlock(p, n), - NodeStructCtor(n) => EntryStructCtor(p, n), - NodeLifetime(n) => EntryLifetime(p, n) - } - } - - fn parent(self) -> Option { - Some(match self { - EntryItem(id, _) => id, - EntryForeignItem(id, _) => id, - EntryTraitItem(id, _) => id, - EntryImplItem(id, _) => id, - EntryVariant(id, _) => id, - EntryExpr(id, _) => id, - EntryStmt(id, _) => id, - EntryArg(id, _) => id, - EntryLocal(id, _) => id, - EntryPat(id, _) => id, - EntryBlock(id, _) => id, - EntryStructCtor(id, _) => id, - EntryLifetime(id, _) => id, - _ => return None - }) - } - - fn to_node(self) -> Option> { - Some(match self { - EntryItem(_, n) => NodeItem(n), - EntryForeignItem(_, n) => NodeForeignItem(n), - EntryTraitItem(_, n) => NodeTraitItem(n), - EntryImplItem(_, n) => NodeImplItem(n), - EntryVariant(_, n) => NodeVariant(n), - EntryExpr(_, n) => NodeExpr(n), - EntryStmt(_, n) => NodeStmt(n), - EntryArg(_, n) => NodeArg(n), - EntryLocal(_, n) => NodeLocal(n), - EntryPat(_, n) => NodePat(n), - EntryBlock(_, n) => NodeBlock(n), - EntryStructCtor(_, n) => NodeStructCtor(n), - EntryLifetime(_, n) => NodeLifetime(n), - _ => return None - }) - } -} - -/// Stores a crate and any number of inlined items from other crates. -pub struct Forest { - krate: Crate, - inlined_items: TypedArena -} - -impl Forest { - pub fn new(krate: Crate) -> Forest { - Forest { - krate: krate, - inlined_items: TypedArena::new() - } - } - - pub fn krate<'ast>(&'ast self) -> &'ast Crate { - &self.krate - } -} - -/// Represents a mapping from Node IDs to AST elements and their parent -/// Node IDs -pub struct Map<'ast> { - /// The backing storage for all the AST nodes. - forest: &'ast Forest, - - /// NodeIds are sequential integers from 0, so we can be - /// super-compact by storing them in a vector. Not everything with - /// a NodeId is in the map, but empirically the occupancy is about - /// 75-80%, so there's not too much overhead (certainly less than - /// a hashmap, since they (at the time of writing) have a maximum - /// of 75% occupancy). - /// - /// Also, indexing is pretty quick when you've got a vector and - /// plain old integers. - map: RefCell>> -} - -impl<'ast> Map<'ast> { - fn entry_count(&self) -> usize { - self.map.borrow().len() - } - - fn find_entry(&self, id: NodeId) -> Option> { - self.map.borrow().get(id as usize).cloned() - } - - pub fn krate(&self) -> &'ast Crate { - &self.forest.krate - } - - /// Retrieve the Node corresponding to `id`, panicking if it cannot - /// be found. - pub fn get(&self, id: NodeId) -> Node<'ast> { - match self.find(id) { - Some(node) => node, - None => panic!("couldn't find node id {} in the AST map", id) - } - } - - /// Retrieve the Node corresponding to `id`, returning None if - /// cannot be found. - pub fn find(&self, id: NodeId) -> Option> { - self.find_entry(id).and_then(|x| x.to_node()) - } - - /// Retrieve the parent NodeId for `id`, or `id` itself if no - /// parent is registered in this map. - pub fn get_parent(&self, id: NodeId) -> NodeId { - self.find_entry(id).and_then(|x| x.parent()).unwrap_or(id) - } - - pub fn get_parent_did(&self, id: NodeId) -> DefId { - let parent = self.get_parent(id); - match self.find_entry(parent) { - Some(RootInlinedParent(&InlinedParent {ii: IITraitItem(did, _), ..})) => did, - Some(RootInlinedParent(&InlinedParent {ii: IIImplItem(did, _), ..})) => did, - _ => ast_util::local_def(parent) - } - } - - pub fn get_foreign_abi(&self, id: NodeId) -> abi::Abi { - let parent = self.get_parent(id); - let abi = match self.find_entry(parent) { - Some(EntryItem(_, i)) => { - match i.node { - ItemForeignMod(ref nm) => Some(nm.abi), - _ => None - } - } - /// Wrong but OK, because the only inlined foreign items are intrinsics. - Some(RootInlinedParent(_)) => Some(abi::RustIntrinsic), - _ => None - }; - match abi { - Some(abi) => abi, - None => panic!("expected foreign mod or inlined parent, found {}", - self.node_to_string(parent)) - } - } - - pub fn get_foreign_vis(&self, id: NodeId) -> Visibility { - let vis = self.expect_foreign_item(id).vis; - match self.find(self.get_parent(id)) { - Some(NodeItem(i)) => vis.inherit_from(i.vis), - _ => vis - } - } - - pub fn expect_item(&self, id: NodeId) -> &'ast Item { - match self.find(id) { - Some(NodeItem(item)) => item, - _ => panic!("expected item, found {}", self.node_to_string(id)) - } - } - - pub fn expect_struct(&self, id: NodeId) -> &'ast StructDef { - match self.find(id) { - Some(NodeItem(i)) => { - match i.node { - ItemStruct(ref struct_def, _) => &**struct_def, - _ => panic!("struct ID bound to non-struct") - } - } - Some(NodeVariant(variant)) => { - match variant.node.kind { - StructVariantKind(ref struct_def) => &**struct_def, - _ => panic!("struct ID bound to enum variant that isn't struct-like"), - } - } - _ => panic!(format!("expected struct, found {}", self.node_to_string(id))), - } - } - - pub fn expect_variant(&self, id: NodeId) -> &'ast Variant { - match self.find(id) { - Some(NodeVariant(variant)) => variant, - _ => panic!(format!("expected variant, found {}", self.node_to_string(id))), - } - } - - pub fn expect_foreign_item(&self, id: NodeId) -> &'ast ForeignItem { - match self.find(id) { - Some(NodeForeignItem(item)) => item, - _ => panic!("expected foreign item, found {}", self.node_to_string(id)) - } - } - - pub fn expect_expr(&self, id: NodeId) -> &'ast Expr { - match self.find(id) { - Some(NodeExpr(expr)) => expr, - _ => panic!("expected expr, found {}", self.node_to_string(id)) - } - } - - /// returns the name associated with the given NodeId's AST - pub fn get_path_elem(&self, id: NodeId) -> PathElem { - let node = self.get(id); - match node { - NodeItem(item) => { - match item.node { - ItemMod(_) | ItemForeignMod(_) => { - PathMod(item.ident.name) - } - _ => PathName(item.ident.name) - } - } - NodeForeignItem(i) => PathName(i.ident.name), - NodeImplItem(ii) => PathName(ii.ident.name), - NodeTraitItem(ti) => PathName(ti.ident.name), - NodeVariant(v) => PathName(v.node.name.name), - _ => panic!("no path elem for {:?}", node) - } - } - - pub fn with_path(&self, id: NodeId, f: F) -> T where - F: FnOnce(PathElems) -> T, - { - self.with_path_next(id, LinkedPath::empty(), f) - } - - pub fn path_to_string(&self, id: NodeId) -> String { - self.with_path(id, |path| path_to_string(path)) - } - - fn path_to_str_with_ident(&self, id: NodeId, i: Ident) -> String { - self.with_path(id, |path| { - path_to_string(path.chain(Some(PathName(i.name)).into_iter())) - }) - } - - fn with_path_next(&self, id: NodeId, next: LinkedPath, f: F) -> T where - F: FnOnce(PathElems) -> T, - { - let parent = self.get_parent(id); - let parent = match self.find_entry(id) { - Some(EntryForeignItem(..)) | Some(EntryVariant(..)) => { - // Anonymous extern items, enum variants and struct ctors - // go in the parent scope. - self.get_parent(parent) - } - // But tuple struct ctors don't have names, so use the path of its - // parent, the struct item. Similarly with closure expressions. - Some(EntryStructCtor(..)) | Some(EntryExpr(..)) => { - return self.with_path_next(parent, next, f); - } - _ => parent - }; - if parent == id { - match self.find_entry(id) { - Some(RootInlinedParent(data)) => { - f(data.path.iter().cloned().chain(next)) - } - _ => f([].iter().cloned().chain(next)) - } - } else { - self.with_path_next(parent, LinkedPath::from(&LinkedPathNode { - node: self.get_path_elem(id), - next: next - }), f) - } - } - - /// Given a node ID, get a list of of attributes associated with the AST - /// corresponding to the Node ID - pub fn attrs(&self, id: NodeId) -> &'ast [Attribute] { - let attrs = match self.find(id) { - Some(NodeItem(i)) => Some(&i.attrs[..]), - Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]), - Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]), - Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]), - Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]), - // unit/tuple structs take the attributes straight from - // the struct definition. - Some(NodeStructCtor(_)) => { - return self.attrs(self.get_parent(id)); - } - _ => None - }; - attrs.unwrap_or(&[]) - } - - /// Returns an iterator that yields the node id's with paths that - /// match `parts`. (Requires `parts` is non-empty.) - /// - /// For example, if given `parts` equal to `["bar", "quux"]`, then - /// the iterator will produce node id's for items with paths - /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and - /// any other such items it can find in the map. - pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String]) - -> NodesMatchingSuffix<'a, 'ast> { - NodesMatchingSuffix { - map: self, - item_name: parts.last().unwrap(), - in_which: &parts[..parts.len() - 1], - idx: 0, - } - } - - pub fn opt_span(&self, id: NodeId) -> Option { - let sp = match self.find(id) { - Some(NodeItem(item)) => item.span, - Some(NodeForeignItem(foreign_item)) => foreign_item.span, - Some(NodeTraitItem(trait_method)) => trait_method.span, - Some(NodeImplItem(ref impl_item)) => impl_item.span, - Some(NodeVariant(variant)) => variant.span, - Some(NodeExpr(expr)) => expr.span, - Some(NodeStmt(stmt)) => stmt.span, - Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span, - Some(NodePat(pat)) => pat.span, - Some(NodeBlock(block)) => block.span, - Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span, - _ => return None, - }; - Some(sp) - } - - pub fn span(&self, id: NodeId) -> Span { - self.opt_span(id) - .unwrap_or_else(|| panic!("AstMap.span: could not find span for id {:?}", id)) - } - - pub fn def_id_span(&self, def_id: DefId, fallback: Span) -> Span { - if def_id.krate == LOCAL_CRATE { - self.opt_span(def_id.node).unwrap_or(fallback) - } else { - fallback - } - } - - pub fn node_to_string(&self, id: NodeId) -> String { - node_id_to_string(self, id, true) - } - - pub fn node_to_user_string(&self, id: NodeId) -> String { - node_id_to_string(self, id, false) - } -} - -pub struct NodesMatchingSuffix<'a, 'ast:'a> { - map: &'a Map<'ast>, - item_name: &'a String, - in_which: &'a [String], - idx: NodeId, -} - -impl<'a, 'ast> NodesMatchingSuffix<'a, 'ast> { - /// Returns true only if some suffix of the module path for parent - /// matches `self.in_which`. - /// - /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`; - /// returns true if parent's path ends with the suffix - /// `x_0::x_1::...::x_k`. - fn suffix_matches(&self, parent: NodeId) -> bool { - let mut cursor = parent; - for part in self.in_which.iter().rev() { - let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) { - None => return false, - Some((node_id, name)) => (node_id, name), - }; - if &part[..] != mod_name.as_str() { - return false; - } - cursor = self.map.get_parent(mod_id); - } - return true; - - // Finds the first mod in parent chain for `id`, along with - // that mod's name. - // - // If `id` itself is a mod named `m` with parent `p`, then - // returns `Some(id, m, p)`. If `id` has no mod in its parent - // chain, then returns `None`. - fn find_first_mod_parent<'a>(map: &'a Map, mut id: NodeId) -> Option<(NodeId, Name)> { - loop { - match map.find(id) { - None => return None, - Some(NodeItem(item)) if item_is_mod(&*item) => - return Some((id, item.ident.name)), - _ => {} - } - let parent = map.get_parent(id); - if parent == id { return None } - id = parent; - } - - fn item_is_mod(item: &Item) -> bool { - match item.node { - ItemMod(_) => true, - _ => false, - } - } - } - } - - // We are looking at some node `n` with a given name and parent - // id; do their names match what I am seeking? - fn matches_names(&self, parent_of_n: NodeId, name: Name) -> bool { - name.as_str() == &self.item_name[..] && - self.suffix_matches(parent_of_n) - } -} - -impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> { - type Item = NodeId; - - fn next(&mut self) -> Option { - loop { - let idx = self.idx; - if idx as usize >= self.map.entry_count() { - return None; - } - self.idx += 1; - let (p, name) = match self.map.find_entry(idx) { - Some(EntryItem(p, n)) => (p, n.name()), - Some(EntryForeignItem(p, n))=> (p, n.name()), - Some(EntryTraitItem(p, n)) => (p, n.name()), - Some(EntryImplItem(p, n)) => (p, n.name()), - Some(EntryVariant(p, n)) => (p, n.name()), - _ => continue, - }; - if self.matches_names(p, name) { - return Some(idx) - } - } - } -} - -trait Named { - fn name(&self) -> Name; -} - -impl Named for Spanned { fn name(&self) -> Name { self.node.name() } } - -impl Named for Item { fn name(&self) -> Name { self.ident.name } } -impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } } -impl Named for Variant_ { fn name(&self) -> Name { self.name.name } } -impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } } -impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } } - -pub trait FoldOps { - fn new_id(&self, id: NodeId) -> NodeId { - id - } - fn new_def_id(&self, def_id: DefId) -> DefId { - def_id - } - fn new_span(&self, span: Span) -> Span { - span - } -} - -/// A Folder that updates IDs and Span's according to fold_ops. -struct IdAndSpanUpdater { - fold_ops: F -} - -impl Folder for IdAndSpanUpdater { - fn new_id(&mut self, id: NodeId) -> NodeId { - self.fold_ops.new_id(id) - } - - fn new_span(&mut self, span: Span) -> Span { - self.fold_ops.new_span(span) - } -} - -/// A Visitor that walks over an AST and collects Node's into an AST Map. -struct NodeCollector<'ast> { - map: Vec>, - /// The node in which we are currently mapping (an item or a method). - parent: NodeId -} - -impl<'ast> NodeCollector<'ast> { - fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) { - debug!("ast_map: {:?} => {:?}", id, entry); - let len = self.map.len(); - if id as usize >= len { - self.map.extend(repeat(NotPresent).take(id as usize - len + 1)); - } - self.map[id as usize] = entry; - } - - fn insert(&mut self, id: NodeId, node: Node<'ast>) { - let entry = MapEntry::from_node(self.parent, node); - self.insert_entry(id, entry); - } - - fn visit_fn_decl(&mut self, decl: &'ast FnDecl) { - for a in &decl.inputs { - self.insert(a.id, NodeArg(&*a.pat)); - } - } -} - -impl<'ast> Visitor<'ast> for NodeCollector<'ast> { - fn visit_item(&mut self, i: &'ast Item) { - self.insert(i.id, NodeItem(i)); - let parent = self.parent; - self.parent = i.id; - match i.node { - ItemImpl(_, _, _, _, _, ref impl_items) => { - for ii in impl_items { - self.insert(ii.id, NodeImplItem(ii)); - } - } - ItemEnum(ref enum_definition, _) => { - for v in &enum_definition.variants { - self.insert(v.node.id, NodeVariant(&**v)); - } - } - ItemForeignMod(ref nm) => { - for nitem in &nm.items { - self.insert(nitem.id, NodeForeignItem(&**nitem)); - } - } - ItemStruct(ref struct_def, _) => { - // If this is a tuple-like struct, register the constructor. - match struct_def.ctor_id { - Some(ctor_id) => { - self.insert(ctor_id, NodeStructCtor(&**struct_def)); - } - None => {} - } - } - ItemTrait(_, _, ref bounds, ref trait_items) => { - for b in &**bounds { - if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b { - self.insert(t.trait_ref.ref_id, NodeItem(i)); - } - } - - for ti in trait_items { - self.insert(ti.id, NodeTraitItem(ti)); - } - } - ItemUse(ref view_path) => { - match view_path.node { - ViewPathList(_, ref paths) => { - for path in paths { - self.insert(path.node.id(), NodeItem(i)); - } - } - _ => () - } - } - _ => {} - } - visit::walk_item(self, i); - self.parent = parent; - } - - fn visit_trait_item(&mut self, ti: &'ast TraitItem) { - let parent = self.parent; - self.parent = ti.id; - visit::walk_trait_item(self, ti); - self.parent = parent; - } - - fn visit_impl_item(&mut self, ii: &'ast ImplItem) { - let parent = self.parent; - self.parent = ii.id; - visit::walk_impl_item(self, ii); - self.parent = parent; - } - - fn visit_pat(&mut self, pat: &'ast Pat) { - self.insert(pat.id, match pat.node { - // Note: this is at least *potentially* a pattern... - PatIdent(..) => NodeLocal(pat), - _ => NodePat(pat) - }); - visit::walk_pat(self, pat); - } - - fn visit_expr(&mut self, expr: &'ast Expr) { - self.insert(expr.id, NodeExpr(expr)); - visit::walk_expr(self, expr); - } - - fn visit_stmt(&mut self, stmt: &'ast Stmt) { - self.insert(ast_util::stmt_id(stmt), NodeStmt(stmt)); - visit::walk_stmt(self, stmt); - } - - fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl, - b: &'ast Block, s: Span, _: NodeId) { - self.visit_fn_decl(fd); - visit::walk_fn(self, fk, fd, b, s); - } - - fn visit_ty(&mut self, ty: &'ast Ty) { - match ty.node { - TyBareFn(ref fd) => { - self.visit_fn_decl(&*fd.decl); - } - _ => {} - } - visit::walk_ty(self, ty); - } - - fn visit_block(&mut self, block: &'ast Block) { - self.insert(block.id, NodeBlock(block)); - visit::walk_block(self, block); - } - - fn visit_lifetime_ref(&mut self, lifetime: &'ast Lifetime) { - self.insert(lifetime.id, NodeLifetime(lifetime)); - } - - fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) { - self.visit_lifetime_ref(&def.lifetime); - } -} - -pub fn map_crate<'ast, F: FoldOps>(forest: &'ast mut Forest, fold_ops: F) -> Map<'ast> { - // Replace the crate with an empty one to take it out. - let krate = mem::replace(&mut forest.krate, Crate { - module: Mod { - inner: DUMMY_SP, - items: vec![], - }, - attrs: vec![], - config: vec![], - exported_macros: vec![], - span: DUMMY_SP - }); - forest.krate = IdAndSpanUpdater { fold_ops: fold_ops }.fold_crate(krate); - - let mut collector = NodeCollector { - map: vec![], - parent: CRATE_NODE_ID - }; - collector.insert_entry(CRATE_NODE_ID, RootCrate); - visit::walk_crate(&mut collector, &forest.krate); - let map = collector.map; - - if log_enabled!(::log::DEBUG) { - // This only makes sense for ordered stores; note the - // enumerate to count the number of entries. - let (entries_less_1, _) = map.iter().filter(|&x| { - match *x { - NotPresent => false, - _ => true - } - }).enumerate().last().expect("AST map was empty after folding?"); - - let entries = entries_less_1 + 1; - let vector_length = map.len(); - debug!("The AST map has {} entries with a maximum of {}: occupancy {:.1}%", - entries, vector_length, (entries as f64 / vector_length as f64) * 100.); - } - - Map { - forest: forest, - map: RefCell::new(map) - } -} - -/// Used for items loaded from external crate that are being inlined into this -/// crate. The `path` should be the path to the item but should not include -/// the item itself. -pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>, - path: Vec, - ii: InlinedItem, - fold_ops: F) - -> &'ast InlinedItem { - let mut fld = IdAndSpanUpdater { fold_ops: fold_ops }; - let ii = match ii { - IIItem(i) => IIItem(fld.fold_item(i).expect_one("expected one item")), - IITraitItem(d, ti) => { - IITraitItem(fld.fold_ops.new_def_id(d), - fld.fold_trait_item(ti).expect_one("expected one trait item")) - } - IIImplItem(d, ii) => { - IIImplItem(fld.fold_ops.new_def_id(d), - fld.fold_impl_item(ii).expect_one("expected one impl item")) - } - IIForeign(i) => IIForeign(fld.fold_foreign_item(i)) - }; - - let ii_parent = map.forest.inlined_items.alloc(InlinedParent { - path: path, - ii: ii - }); - - let mut collector = NodeCollector { - map: mem::replace(&mut *map.map.borrow_mut(), vec![]), - parent: fld.new_id(DUMMY_NODE_ID) - }; - let ii_parent_id = collector.parent; - collector.insert_entry(ii_parent_id, RootInlinedParent(ii_parent)); - visit::walk_inlined_item(&mut collector, &ii_parent.ii); - - // Methods get added to the AST map when their impl is visited. Since we - // don't decode and instantiate the impl, but just the method, we have to - // add it to the table now. Likewise with foreign items. - match ii_parent.ii { - IIItem(_) => {} - IITraitItem(_, ref ti) => { - collector.insert(ti.id, NodeTraitItem(ti)); - } - IIImplItem(_, ref ii) => { - collector.insert(ii.id, NodeImplItem(ii)); - } - IIForeign(ref i) => { - collector.insert(i.id, NodeForeignItem(i)); - } - } - *map.map.borrow_mut() = collector.map; - &ii_parent.ii -} - -pub trait NodePrinter { - fn print_node(&mut self, node: &Node) -> io::Result<()>; -} - -impl<'a> NodePrinter for pprust::State<'a> { - fn print_node(&mut self, node: &Node) -> io::Result<()> { - match *node { - NodeItem(a) => self.print_item(&*a), - NodeForeignItem(a) => self.print_foreign_item(&*a), - NodeTraitItem(a) => self.print_trait_item(a), - NodeImplItem(a) => self.print_impl_item(a), - NodeVariant(a) => self.print_variant(&*a), - NodeExpr(a) => self.print_expr(&*a), - NodeStmt(a) => self.print_stmt(&*a), - NodePat(a) => self.print_pat(&*a), - NodeBlock(a) => self.print_block(&*a), - NodeLifetime(a) => self.print_lifetime(&*a), - - // these cases do not carry enough information in the - // ast_map to reconstruct their full structure for pretty - // printing. - NodeLocal(_) => panic!("cannot print isolated Local"), - NodeArg(_) => panic!("cannot print isolated Arg"), - NodeStructCtor(_) => panic!("cannot print isolated StructCtor"), - } - } -} - -fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { - let id_str = format!(" (id={})", id); - let id_str = if include_id { &id_str[..] } else { "" }; - - match map.find(id) { - Some(NodeItem(item)) => { - let path_str = map.path_to_str_with_ident(id, item.ident); - let item_str = match item.node { - ItemExternCrate(..) => "extern crate", - ItemUse(..) => "use", - ItemStatic(..) => "static", - ItemConst(..) => "const", - ItemFn(..) => "fn", - ItemMod(..) => "mod", - ItemForeignMod(..) => "foreign mod", - ItemTy(..) => "ty", - ItemEnum(..) => "enum", - ItemStruct(..) => "struct", - ItemTrait(..) => "trait", - ItemImpl(..) => "impl", - ItemDefaultImpl(..) => "default impl", - ItemMac(..) => "macro" - }; - format!("{} {}{}", item_str, path_str, id_str) - } - Some(NodeForeignItem(item)) => { - let path_str = map.path_to_str_with_ident(id, item.ident); - format!("foreign item {}{}", path_str, id_str) - } - Some(NodeImplItem(ii)) => { - match ii.node { - ConstImplItem(..) => { - format!("assoc const {} in {}{}", - token::get_ident(ii.ident), - map.path_to_string(id), - id_str) - } - MethodImplItem(..) => { - format!("method {} in {}{}", - token::get_ident(ii.ident), - map.path_to_string(id), id_str) - } - TypeImplItem(_) => { - format!("assoc type {} in {}{}", - token::get_ident(ii.ident), - map.path_to_string(id), - id_str) - } - MacImplItem(ref mac) => { - format!("method macro {}{}", - pprust::mac_to_string(mac), id_str) - } - } - } - Some(NodeTraitItem(ti)) => { - let kind = match ti.node { - ConstTraitItem(..) => "assoc constant", - MethodTraitItem(..) => "trait method", - TypeTraitItem(..) => "assoc type", - }; - - format!("{} {} in {}{}", - kind, - token::get_ident(ti.ident), - map.path_to_string(id), - id_str) - } - Some(NodeVariant(ref variant)) => { - format!("variant {} in {}{}", - token::get_ident(variant.node.name), - map.path_to_string(id), id_str) - } - Some(NodeExpr(ref expr)) => { - format!("expr {}{}", pprust::expr_to_string(&**expr), id_str) - } - Some(NodeStmt(ref stmt)) => { - format!("stmt {}{}", pprust::stmt_to_string(&**stmt), id_str) - } - Some(NodeArg(ref pat)) => { - format!("arg {}{}", pprust::pat_to_string(&**pat), id_str) - } - Some(NodeLocal(ref pat)) => { - format!("local {}{}", pprust::pat_to_string(&**pat), id_str) - } - Some(NodePat(ref pat)) => { - format!("pat {}{}", pprust::pat_to_string(&**pat), id_str) - } - Some(NodeBlock(ref block)) => { - format!("block {}{}", pprust::block_to_string(&**block), id_str) - } - Some(NodeStructCtor(_)) => { - format!("struct_ctor {}{}", map.path_to_string(id), id_str) - } - Some(NodeLifetime(ref l)) => { - format!("lifetime {}{}", - pprust::lifetime_to_string(&**l), id_str) - } - None => { - format!("unknown node{}", id_str) - } - } -} diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 20f8c9707bf..11c4b0f1261 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -35,7 +35,6 @@ #![feature(str_char)] #![feature(unicode)] -extern crate arena; extern crate fmt_macros; extern crate serialize; extern crate term; @@ -82,7 +81,6 @@ pub mod syntax { pub mod abi; pub mod ast; -pub mod ast_map; pub mod ast_util; pub mod attr; pub mod codemap; diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs index ba6d0d246e4..5c15a56c6ef 100644 --- a/src/test/run-make/execution-engine/test.rs +++ b/src/test/run-make/execution-engine/test.rs @@ -21,6 +21,7 @@ use std::mem::transmute; use std::path::PathBuf; use std::thread::Builder; +use rustc::ast_map; use rustc::llvm; use rustc::metadata::cstore::RequireDynamic; use rustc::middle::ty; @@ -29,7 +30,6 @@ use rustc::session::build_session; use rustc_driver::driver; use rustc_resolve::MakeGlobMap; -use syntax::ast_map; use syntax::diagnostics::registry::Registry; fn main() { -- cgit 1.4.1-3-g733a5