rustc: embed path resolutions into the HIR instead of keeping DefMap.

This commit is contained in:
Eduard-Mihai Burtescu 2016-11-25 13:21:19 +02:00
parent bc096549e8
commit 962633cdbb
55 changed files with 951 additions and 949 deletions

View file

@ -29,24 +29,21 @@ use clean::{self, GetDefId};
use super::Clean;
/// Attempt to inline the definition of a local node id into this AST.
/// Attempt to inline a definition into this AST.
///
/// This function will fetch the definition of the id specified, and if it is
/// from another crate it will attempt to inline the documentation from the
/// other crate into this crate.
/// This function will fetch the definition specified, and if it is
/// from another crate it will attempt to inline the documentation
/// from the other crate into this crate.
///
/// This is primarily used for `pub use` statements which are, in general,
/// implementation details. Inlining the documentation should help provide a
/// better experience when reading the documentation in this use case.
///
/// The returned value is `None` if the `id` could not be inlined, and `Some`
/// of a vector of items if it was successfully expanded.
pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Name>)
/// The returned value is `None` if the definition could not be inlined,
/// and `Some` of a vector of items if it was successfully expanded.
pub fn try_inline(cx: &DocContext, def: Def, into: Option<ast::Name>)
-> Option<Vec<clean::Item>> {
let def = match cx.tcx.expect_def_or_none(id) {
Some(def) => def,
None => return None,
};
if def == Def::Err { return None }
let did = def.def_id();
if did.is_local() { return None }
try_inline_def(cx, def).map(|vec| {

View file

@ -667,6 +667,7 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self
bindings: Vec<TypeBinding>, substs: &Substs) -> Path {
Path {
global: false,
def: Def::Err,
segments: vec![PathSegment {
name: name.to_string(),
params: external_path_params(cx, trait_did, has_self, bindings, substs)
@ -1728,13 +1729,12 @@ impl Clean<Type> for hir::Ty {
},
TyTup(ref tys) => Tuple(tys.clean(cx)),
TyPath(hir::QPath::Resolved(None, ref path)) => {
let def = cx.tcx.expect_def(self.id);
if let Some(new_ty) = cx.ty_substs.borrow().get(&def).cloned() {
if let Some(new_ty) = cx.ty_substs.borrow().get(&path.def).cloned() {
return new_ty;
}
let mut alias = None;
if let Def::TyAlias(def_id) = def {
if let Def::TyAlias(def_id) = path.def {
// Substitute private type aliases
if let Some(node_id) = cx.tcx.map.as_local_node_id(def_id) {
if !cx.access_levels.borrow().is_exported(def_id) {
@ -1748,7 +1748,7 @@ impl Clean<Type> for hir::Ty {
let mut ty_substs = FxHashMap();
let mut lt_substs = FxHashMap();
for (i, ty_param) in generics.ty_params.iter().enumerate() {
let ty_param_def = cx.tcx.expect_def(ty_param.id);
let ty_param_def = Def::TyParam(cx.tcx.map.local_def_id(ty_param.id));
if let Some(ty) = provided_params.types().get(i).cloned()
.cloned() {
ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
@ -1772,6 +1772,7 @@ impl Clean<Type> for hir::Ty {
let trait_path = hir::Path {
span: p.span,
global: p.global,
def: Def::Trait(cx.tcx.associated_item(p.def.def_id()).container.id()),
segments: segments.into(),
};
Type::QPath {
@ -1784,6 +1785,10 @@ impl Clean<Type> for hir::Ty {
let trait_path = hir::Path {
span: self.span,
global: false,
def: cx.tcx_opt().map_or(Def::Err, |tcx| {
let def_id = tcx.tables().type_relative_path_defs[&self.id].def_id();
Def::Trait(tcx.associated_item(def_id).container.id())
}),
segments: vec![].into(),
};
Type::QPath {
@ -2194,6 +2199,7 @@ impl Clean<Span> for syntax_pos::Span {
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub struct Path {
pub global: bool,
pub def: Def,
pub segments: Vec<PathSegment>,
}
@ -2201,6 +2207,7 @@ impl Path {
pub fn singleton(name: String) -> Path {
Path {
global: false,
def: Def::Err,
segments: vec![PathSegment {
name: name,
params: PathParameters::AngleBracketed {
@ -2221,6 +2228,7 @@ impl Clean<Path> for hir::Path {
fn clean(&self, cx: &DocContext) -> Path {
Path {
global: self.global,
def: self.def,
segments: self.segments.clean(cx),
}
}
@ -2591,15 +2599,15 @@ impl Clean<Vec<Item>> for doctree::Import {
});
let path = self.path.clean(cx);
let inner = if self.glob {
Import::Glob(resolve_use_source(cx, path, self.id))
Import::Glob(resolve_use_source(cx, path))
} else {
let name = self.name;
if !denied {
if let Some(items) = inline::try_inline(cx, self.id, Some(name)) {
if let Some(items) = inline::try_inline(cx, path.def, Some(name)) {
return items;
}
}
Import::Simple(name.clean(cx), resolve_use_source(cx, path, self.id))
Import::Simple(name.clean(cx), resolve_use_source(cx, path))
};
vec![Item {
name: None,
@ -2697,7 +2705,7 @@ fn name_from_pat(p: &hir::Pat) -> String {
match p.node {
PatKind::Wild => "_".to_string(),
PatKind::Binding(_, ref p, _) => p.node.to_string(),
PatKind::Binding(_, _, ref p, _) => p.node.to_string(),
PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
PatKind::Struct(ref name, ref fields, etc) => {
format!("{} {{ {}{} }}", qpath_to_string(name),
@ -2727,15 +2735,13 @@ fn name_from_pat(p: &hir::Pat) -> String {
}
}
/// Given a Type, resolve it using the def_map
/// Given a type Path, resolve it to a Type using the TyCtxt
fn resolve_type(cx: &DocContext,
path: Path,
id: ast::NodeId) -> Type {
debug!("resolve_type({:?},{:?})", path, id);
let def = cx.tcx.expect_def(id);
debug!("resolve_type: def={:?}", def);
let is_generic = match def {
let is_generic = match path.def {
Def::PrimTy(p) => match p {
hir::TyStr => return Primitive(PrimitiveType::Str),
hir::TyBool => return Primitive(PrimitiveType::Bool),
@ -2750,7 +2756,7 @@ fn resolve_type(cx: &DocContext,
Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true,
_ => false,
};
let did = register_def(&*cx, def);
let did = register_def(&*cx, path.def);
ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
}
@ -2782,17 +2788,17 @@ fn register_def(cx: &DocContext, def: Def) -> DefId {
did
}
fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSource {
fn resolve_use_source(cx: &DocContext, path: Path) -> ImportSource {
ImportSource {
did: if path.def == Def::Err {
None
} else {
Some(register_def(cx, path.def))
},
path: path,
did: resolve_def(cx, id),
}
}
fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<DefId> {
cx.tcx.expect_def_or_none(id).map(|def| register_def(cx, def))
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Macro {
pub source: String,
@ -2896,6 +2902,7 @@ fn lang_struct(cx: &DocContext, did: Option<DefId>,
did: did,
path: Path {
global: false,
def: Def::Err,
segments: vec![PathSegment {
name: name.to_string(),
params: PathParameters::AngleBracketed {

View file

@ -234,8 +234,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
/// and follows different rules.
///
/// Returns true if the target has been inlined.
fn maybe_inline_local(&mut self, id: ast::NodeId, renamed: Option<ast::Name>,
glob: bool, om: &mut Module, please_inline: bool) -> bool {
fn maybe_inline_local(&mut self,
id: ast::NodeId,
def: Def,
renamed: Option<ast::Name>,
glob: bool,
om: &mut Module,
please_inline: bool) -> bool {
fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool {
while let Some(id) = cx.tcx.map.get_enclosing_scope(node) {
@ -251,7 +256,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
}
let tcx = self.cx.tcx;
let def = tcx.expect_def(id);
if def == Def::Err {
return false;
}
let def_did = def.def_id();
let use_attrs = tcx.map.attrs(id);
@ -368,13 +375,18 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
}
});
let name = if is_glob { None } else { Some(name) };
if self.maybe_inline_local(item.id, name, is_glob, om, please_inline) {
if self.maybe_inline_local(item.id,
path.def,
name,
is_glob,
om,
please_inline) {
return;
}
}
om.imports.push(Import {
name: item.name,
name: name,
id: item.id,
vis: item.vis.clone(),
attrs: item.attrs.clone(),