track def-id for inlined items

This commit is contained in:
Niko Matsakis 2016-03-16 05:31:51 -04:00
parent 2475707322
commit 65c0b7c292
5 changed files with 72 additions and 16 deletions

View File

@ -14,7 +14,7 @@
use rustc_front::hir::*;
use rustc_front::util;
use rustc_front::intravisit::{self, Visitor};
use middle::def_id::{CRATE_DEF_INDEX, DefIndex};
use middle::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
use std::iter::repeat;
use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
use syntax::codemap::Span;
@ -50,6 +50,7 @@ pub fn extend(krate: &'ast Crate,
parent: &'ast InlinedParent,
parent_node: NodeId,
parent_def_path: DefPath,
parent_def_id: DefId,
map: Vec<MapEntry<'ast>>,
definitions: Definitions)
-> NodeCollector<'ast> {
@ -60,8 +61,14 @@ pub fn extend(krate: &'ast Crate,
definitions: definitions,
};
assert_eq!(parent_def_path.krate, parent_def_id.krate);
let root_path = Box::new(InlinedRootPath {
data: parent_def_path.data,
def_id: parent_def_id,
});
collector.insert_entry(parent_node, RootInlinedParent(parent));
collector.create_def(parent_node, DefPathData::InlinedRoot(parent_def_path));
collector.create_def(parent_node, DefPathData::InlinedRoot(root_path));
collector
}

View File

@ -60,13 +60,38 @@ pub struct DefData {
}
pub type DefPath = Vec<DisambiguatedDefPathData>;
/// Root of an inlined item. We track the `DefPath` of the item within
/// the original crate but also its def-id. This is kind of an
/// augmented version of a `DefPath` that includes a `DefId`. This is
/// all sort of ugly but the hope is that inlined items will be going
/// away soon anyway.
///
/// Some of the constraints that led to the current approach:
///
/// - I don't want to have a `DefId` in the main `DefPath` because
/// that gets serialized for incr. comp., and when reloaded the
/// `DefId` is no longer valid. I'd rather maintain the invariant
/// that every `DefId` is valid, and a potentially outdated `DefId` is
/// represented as a `DefPath`.
/// - (We don't serialize def-paths from inlined items, so it's ok to have one here.)
/// - We need to be able to extract the def-id from inline items to
/// make the symbol name. In theory we could retrace it from the
/// data, but the metadata doesn't have the required indices, and I
/// don't want to write the code to create one just for this.
/// - It may be that we don't actually need `data` at all. We'll have
/// to see about that.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct InlinedRootPath {
pub data: Vec<DisambiguatedDefPathData>,
pub def_id: DefId,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum DefPathData {
// Root: these should only be used for the root nodes, because
// they are treated specially by the `def_path` function.
CrateRoot,
InlinedRoot(DefPath),
InlinedRoot(Box<InlinedRootPath>),
// Catch-all for random DefId things like DUMMY_NODE_ID
Misc,

View File

@ -12,7 +12,8 @@
pub use self::PathElem::*;
use self::MapEntry::*;
use self::collector::NodeCollector;
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData};
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
DisambiguatedDefPathData, InlinedRootPath};
use dep_graph::{DepGraph, DepNode};
@ -322,7 +323,8 @@ fn dep_node(&self, id0: NodeId) -> DepNode {
id = p,
RootCrate |
RootInlinedParent(_) => // FIXME(#2369) clarify story about cross-crate dep tracking
RootInlinedParent(_) =>
// FIXME(#32015) clarify story about cross-crate dep tracking
return DepNode::Krate,
NotPresent =>
@ -958,6 +960,7 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
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,
fold_ops: F)
-> &'ast InlinedItem {
@ -987,6 +990,7 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
ii_parent,
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);

View File

@ -125,6 +125,7 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
tcx: &TyCtxt<'tcx>,
parent_path: Vec<ast_map::PathElem>,
parent_def_path: ast_map::DefPath,
parent_did: DefId,
ast_doc: rbml::Doc,
orig_did: DefId)
-> &'tcx InlinedItem {
@ -149,6 +150,7 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
let ii = ast_map::map_decoded_item(&dcx.tcx.map,
parent_path,
parent_def_path,
parent_did,
decode_ast(ast_doc),
dcx);
let name = match *ii {
@ -349,8 +351,8 @@ fn simplify_ast(ii: InlinedItemRef) -> InlinedItem {
}
}
fn decode_ast(par_doc: rbml::Doc) -> InlinedItem {
let chi_doc = par_doc.get(c::tag_tree as usize);
fn decode_ast(item_doc: rbml::Doc) -> InlinedItem {
let chi_doc = item_doc.get(c::tag_tree as usize);
let mut rbml_r = reader::Decoder::new(chi_doc);
rbml_r.read_opaque(|decoder, _| Decodable::decode(decoder)).unwrap()
}
@ -1280,8 +1282,8 @@ fn encode_item_ast(rbml_w: &mut Encoder, item: &hir::Item) {
}
#[cfg(test)]
fn decode_item_ast(par_doc: rbml::Doc) -> hir::Item {
let chi_doc = par_doc.get(c::tag_tree as usize);
fn decode_item_ast(item_doc: rbml::Doc) -> hir::Item {
let chi_doc = item_doc.get(c::tag_tree as usize);
let mut d = reader::Decoder::new(chi_doc);
Decodable::decode(&mut d).unwrap()
}

View File

@ -803,25 +803,43 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &TyCtxt<'tcx>, id: DefIndex)
debug!("Looking up item: {:?}", id);
let item_doc = cdata.lookup_item(id);
let item_did = item_def_id(item_doc, cdata);
let parent_def_id = DefId {
krate: cdata.cnum,
index: def_key(cdata, id).parent.unwrap()
};
let mut parent_path = item_path(item_doc);
parent_path.pop();
let mut parent_def_path = def_path(cdata, id);
parent_def_path.pop();
if let Some(ast_doc) = reader::maybe_get_doc(item_doc, tag_ast as usize) {
let ii = decode_inlined_item(cdata, tcx, parent_path,
let ii = decode_inlined_item(cdata,
tcx,
parent_path,
parent_def_path,
ast_doc, item_did);
parent_def_id,
ast_doc,
item_did);
return FoundAst::Found(ii);
} else if let Some(parent_did) = item_parent_item(cdata, item_doc) {
// Remove the last element from the paths, since we are now
// trying to inline the parent.
parent_path.pop();
parent_def_path.pop();
let grandparent_def_id = DefId {
krate: cdata.cnum,
index: def_key(cdata, parent_def_id.index).parent.unwrap()
};
let mut grandparent_path = parent_path;
grandparent_path.pop();
let mut grandparent_def_path = parent_def_path;
grandparent_def_path.pop();
let parent_doc = cdata.lookup_item(parent_did.index);
if let Some(ast_doc) = reader::maybe_get_doc(parent_doc, tag_ast as usize) {
let ii = decode_inlined_item(cdata, tcx, parent_path,
parent_def_path,
ast_doc, parent_did);
let ii = decode_inlined_item(cdata,
tcx,
grandparent_path,
grandparent_def_path,
grandparent_def_id,
ast_doc,
parent_did);
if let &InlinedItem::Item(ref i) = ii {
return FoundAst::FoundParent(parent_did, i);
}