rustc: retire hir::map's paths.

This commit is contained in:
Eduard Burtescu 2016-04-06 13:51:55 +03:00
parent 20f0f3c1f1
commit e8a8dfb056
23 changed files with 192 additions and 525 deletions

View file

@ -14,6 +14,7 @@ use super::MapEntry::*;
use hir::*;
use hir::intravisit::Visitor;
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
use middle::cstore::InlinedItem;
use std::iter::repeat;
use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
use syntax::codemap::Span;
@ -46,7 +47,7 @@ impl<'ast> NodeCollector<'ast> {
}
pub fn extend(krate: &'ast Crate,
parent: &'ast InlinedParent,
parent: &'ast InlinedItem,
parent_node: NodeId,
parent_def_path: DefPath,
parent_def_id: DefId,

View file

@ -9,7 +9,6 @@
// except according to those terms.
pub use self::Node::*;
pub use self::PathElem::*;
use self::MapEntry::*;
use self::collector::NodeCollector;
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
@ -25,7 +24,6 @@ use syntax::abi::Abi;
use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID};
use syntax::attr::ThinAttributesExt;
use syntax::codemap::{Span, Spanned};
use syntax::parse::token;
use hir::*;
use hir::fold::Folder;
@ -33,85 +31,13 @@ use hir::print as pprust;
use arena::TypedArena;
use std::cell::RefCell;
use std::fmt;
use std::io;
use std::iter;
use std::mem;
use std::slice;
pub mod blocks;
mod collector;
pub mod definitions;
#[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 {
write!(f, "{}", self.name())
}
}
#[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<PathElem> {
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<iter::Cloned<slice::Iter<'a, PathElem>>, LinkedPath<'b>>;
pub fn path_to_string<PI: Iterator<Item=PathElem>>(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),
@ -156,7 +82,7 @@ pub enum MapEntry<'ast> {
/// Roots for node trees.
RootCrate,
RootInlinedParent(&'ast InlinedParent)
RootInlinedParent(&'ast InlinedItem)
}
impl<'ast> Clone for MapEntry<'ast> {
@ -165,12 +91,6 @@ impl<'ast> Clone for MapEntry<'ast> {
}
}
#[derive(Debug)]
pub struct InlinedParent {
path: Vec<PathElem>,
ii: InlinedItem
}
impl<'ast> MapEntry<'ast> {
fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
match node {
@ -233,7 +153,7 @@ impl<'ast> MapEntry<'ast> {
pub struct Forest {
krate: Crate,
pub dep_graph: DepGraph,
inlined_items: TypedArena<InlinedParent>
inlined_items: TypedArena<InlinedItem>
}
impl Forest {
@ -351,8 +271,10 @@ impl<'ast> Map<'ast> {
self.definitions.borrow().def_key(def_id.index)
}
pub fn def_path_from_id(&self, id: NodeId) -> DefPath {
self.def_path(self.local_def_id(id))
pub fn def_path_from_id(&self, id: NodeId) -> Option<DefPath> {
self.opt_local_def_id(id).map(|def_id| {
self.def_path(def_id)
})
}
pub fn def_path(&self, def_id: DefId) -> DefPath {
@ -551,8 +473,8 @@ impl<'ast> Map<'ast> {
pub fn get_parent_did(&self, id: NodeId) -> DefId {
let parent = self.get_parent(id);
match self.find_entry(parent) {
Some(RootInlinedParent(&InlinedParent {ii: II::TraitItem(did, _), ..})) => did,
Some(RootInlinedParent(&InlinedParent {ii: II::ImplItem(did, _), ..})) => did,
Some(RootInlinedParent(&II::TraitItem(did, _))) |
Some(RootInlinedParent(&II::ImplItem(did, _))) => did,
_ => self.local_def_id(parent)
}
}
@ -634,80 +556,21 @@ impl<'ast> Map<'ast> {
}
}
/// 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.name)
}
_ => PathName(item.name)
}
}
NodeForeignItem(i) => PathName(i.name),
NodeImplItem(ii) => PathName(ii.name),
NodeTraitItem(ti) => PathName(ti.name),
NodeVariant(v) => PathName(v.node.name),
NodeLifetime(lt) => PathName(lt.name),
NodeTyParam(tp) => PathName(tp.name),
/// Returns the name associated with the given NodeId's AST.
pub fn name(&self, id: NodeId) -> Name {
match self.get(id) {
NodeItem(i) => i.name,
NodeForeignItem(i) => i.name,
NodeImplItem(ii) => ii.name,
NodeTraitItem(ti) => ti.name,
NodeVariant(v) => v.node.name,
NodeLifetime(lt) => lt.name,
NodeTyParam(tp) => tp.name,
NodeLocal(&Pat { node: PatKind::Ident(_,l,_), .. }) => {
PathName(l.node.name)
l.node.name
},
_ => bug!("no path elem for {:?}", node)
}
}
pub fn with_path<T, F>(&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_name(&self, id: NodeId, name: Name) -> String {
self.with_path(id, |path| {
path_to_string(path.chain(Some(PathName(name))))
})
}
fn with_path_next<T, F>(&self, id: NodeId, next: LinkedPath, f: F) -> T where
F: FnOnce(PathElems) -> T,
{
// This function reveals the name of the item and hence is a
// kind of read. This is inefficient, since it walks ancestors
// and we are walking them anyhow, but whatever.
self.read(id);
let parent = self.get_parent(id);
let parent = match self.find_entry(id) {
Some(EntryForeignItem(..)) => {
// Anonymous extern items 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)
NodeStructCtor(_) => self.name(self.get_parent(id)),
_ => bug!("no name for {}", self.node_to_string(id))
}
}
@ -958,7 +821,6 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
/// Used for items loaded from external crate that are being inlined into this
/// crate.
pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
parent_path: Vec<PathElem>,
parent_def_path: DefPath,
parent_def_id: DefId,
ii: InlinedItem,
@ -978,27 +840,24 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
II::Foreign(i) => II::Foreign(i.map(|i| fld.fold_foreign_item(i)))
};
let ii_parent = map.forest.inlined_items.alloc(InlinedParent {
path: parent_path,
ii: ii
});
let ii = map.forest.inlined_items.alloc(ii);
let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
let mut collector =
NodeCollector::extend(
map.krate(),
ii_parent,
ii,
ii_parent_id,
parent_def_path,
parent_def_id,
mem::replace(&mut *map.map.borrow_mut(), vec![]),
mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new()));
ii_parent.ii.visit(&mut collector);
ii.visit(&mut collector);
*map.map.borrow_mut() = collector.map;
*map.definitions.borrow_mut() = collector.definitions;
&ii_parent.ii
ii
}
pub trait NodePrinter {
@ -1032,9 +891,24 @@ 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 { "" };
let path_str = || {
// This functionality is used for debugging, try to use TyCtxt to get
// the user-friendly path, otherwise fall back to stringifying DefPath.
::ty::tls::with_opt(|tcx| {
if let Some(tcx) = tcx {
tcx.node_path_str(id)
} else if let Some(path) = map.def_path_from_id(id) {
path.data.into_iter().map(|elem| {
elem.data.to_string()
}).collect::<Vec<_>>().join("::")
} else {
String::from("<missing path>")
}
})
};
match map.find(id) {
Some(NodeItem(item)) => {
let path_str = map.path_to_str_with_name(id, item.name);
let item_str = match item.node {
ItemExternCrate(..) => "extern crate",
ItemUse(..) => "use",
@ -1050,30 +924,21 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
ItemImpl(..) => "impl",
ItemDefaultImpl(..) => "default impl",
};
format!("{} {}{}", item_str, path_str, id_str)
format!("{} {}{}", item_str, path_str(), id_str)
}
Some(NodeForeignItem(item)) => {
let path_str = map.path_to_str_with_name(id, item.name);
format!("foreign item {}{}", path_str, id_str)
Some(NodeForeignItem(_)) => {
format!("foreign item {}{}", path_str(), id_str)
}
Some(NodeImplItem(ii)) => {
match ii.node {
ImplItemKind::Const(..) => {
format!("assoc const {} in {}{}",
ii.name,
map.path_to_string(id),
id_str)
format!("assoc const {} in {}{}", ii.name, path_str(), id_str)
}
ImplItemKind::Method(..) => {
format!("method {} in {}{}",
ii.name,
map.path_to_string(id), id_str)
format!("method {} in {}{}", ii.name, path_str(), id_str)
}
ImplItemKind::Type(_) => {
format!("assoc type {} in {}{}",
ii.name,
map.path_to_string(id),
id_str)
format!("assoc type {} in {}{}", ii.name, path_str(), id_str)
}
}
}
@ -1084,16 +949,12 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
TypeTraitItem(..) => "assoc type",
};
format!("{} {} in {}{}",
kind,
ti.name,
map.path_to_string(id),
id_str)
format!("{} {} in {}{}", kind, ti.name, path_str(), id_str)
}
Some(NodeVariant(ref variant)) => {
format!("variant {} in {}{}",
variant.node.name,
map.path_to_string(id), id_str)
path_str(), id_str)
}
Some(NodeExpr(ref expr)) => {
format!("expr {}{}", pprust::expr_to_string(&expr), id_str)
@ -1111,7 +972,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
format!("block {}{}", pprust::block_to_string(&block), id_str)
}
Some(NodeStructCtor(_)) => {
format!("struct_ctor {}{}", map.path_to_string(id), id_str)
format!("struct_ctor {}{}", path_str(), id_str)
}
Some(NodeLifetime(ref l)) => {
format!("lifetime {}{}",

View file

@ -210,14 +210,8 @@ pub fn simple_name<'a>(pat: &'a hir::Pat) -> Option<ast::Name> {
}
pub fn def_to_path(tcx: &TyCtxt, id: DefId) -> hir::Path {
tcx.with_path(id, |path| hir::Path {
global: false,
segments: path.last().map(|elem| hir::PathSegment {
identifier: hir::Ident::from_name(elem.name()),
parameters: hir::PathParameters::none(),
}).into_iter().collect(),
span: DUMMY_SP,
})
let name = tcx.item_name(id);
hir::Path::from_ident(DUMMY_SP, hir::Ident::from_name(name))
}
/// Return variants that are necessary to exist for the pattern to match.

View file

@ -587,13 +587,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
// Only external crates, if either is from a local
// module we could have false positives
if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
let exp_path = self.tcx.with_path(did1,
|p| p.map(|x| x.to_string())
.collect::<Vec<_>>());
let found_path = self.tcx.with_path(did2,
|p| p.map(|x| x.to_string())
.collect::<Vec<_>>());
// We compare strings because PathMod and PathName can be different
let exp_path = self.tcx.item_path_str(did1);
let found_path = self.tcx.item_path_str(did2);
// We compare strings because DefPath can be different
// for imported and non-imported crates
if exp_path == found_path {
let crate_name = self.tcx.sess.cstore.crate_name(did1.krate);

View file

@ -166,9 +166,7 @@ pub trait CrateStore<'tcx> : Any {
fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr>;
fn item_type(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-> ty::TypeScheme<'tcx>;
fn relative_item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>>;
fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
fn item_name(&self, def: DefId) -> ast::Name;
fn item_predicates(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx>;
@ -345,12 +343,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr> { bug!("repr_attrs") }
fn item_type(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-> ty::TypeScheme<'tcx> { bug!("item_type") }
fn relative_item_path(&self, def: DefId)
-> Vec<hir_map::PathElem> { bug!("relative_item_path") }
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>> {
bug!("visible_parent_map")
}
fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { bug!("extern_item_path") }
fn item_name(&self, def: DefId) -> ast::Name { bug!("item_name") }
fn item_predicates(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx> { bug!("item_predicates") }

View file

@ -24,6 +24,11 @@ impl<'tcx> TyCtxt<'tcx> {
buffer.into_string()
}
/// Returns a string identifying this local node-id.
pub fn node_path_str(&self, id: ast::NodeId) -> String {
self.item_path_str(self.map.local_def_id(id))
}
/// Returns a string identifying this def-id. This string is
/// suitable for user output. It always begins with a crate identifier.
pub fn absolute_item_path_str(&self, def_id: DefId) -> String {

View file

@ -20,7 +20,6 @@ pub use self::fold::TypeFoldable;
use dep_graph::{self, DepNode};
use hir::map as ast_map;
use hir::map::LinkedPath;
use middle;
use middle::cstore::{self, CrateStore, LOCAL_CRATE};
use hir::def::{self, Def, ExportMap};
@ -2231,39 +2230,9 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
pub fn with_path<T, F>(&self, id: DefId, f: F) -> T where
F: FnOnce(ast_map::PathElems) -> T,
{
if let Some(id) = self.map.as_local_node_id(id) {
self.map.with_path(id, f)
} else {
let mut path: Vec<_>;
if let Some(extern_crate) = self.sess.cstore.extern_crate(id.krate) {
if !extern_crate.direct {
// this comes from some crate that we don't have a direct
// path to; we'll settle for just prepending the name of
// the crate.
path = self.sess.cstore.extern_item_path(id)
} else {
// start with the path to the extern crate, then
// add the relative path to the actual item
fn collector(elems: ast_map::PathElems) -> Vec<ast_map::PathElem> {
elems.collect()
}
path = self.with_path(extern_crate.def_id, collector);
path.extend(self.sess.cstore.relative_item_path(id));
}
} else {
// if this was injected, just make a path with name of crate
path = self.sess.cstore.extern_item_path(id);
}
f(path.iter().cloned().chain(LinkedPath::empty()))
}
}
pub fn item_name(&self, id: DefId) -> ast::Name {
if let Some(id) = self.map.as_local_node_id(id) {
self.map.get_path_elem(id).name()
self.map.name(id)
} else {
self.sess.cstore.item_name(id)
}