rustdoc: Suck in all impls from external crates

There is currently no way to query all impls for a type from an external crate,
and with primitive types in play this is also quite difficult. Instead of
filtering, just suck in all impls from upstream crates into the local AST, and
have them get stripped later.

This will allow population of all implementations of traits for primitive types,
as well as filling in some corner cases with inlining documentation in other
cases.
This commit is contained in:
Alex Crichton 2014-05-29 01:35:44 -07:00
parent c2564b8fd4
commit 8c669d7f74
3 changed files with 41 additions and 4 deletions

View File

@ -67,12 +67,12 @@ fn try_inline_def(cx: &core::DocContext,
}
ast::DefStruct(did) => {
record_extern_fqn(cx, did, clean::TypeStruct);
ret.extend(build_impls(tcx, did).move_iter());
ret.extend(build_impls(cx, tcx, did).move_iter());
clean::StructItem(build_struct(tcx, did))
}
ast::DefTy(did) => {
record_extern_fqn(cx, did, clean::TypeEnum);
ret.extend(build_impls(tcx, did).move_iter());
ret.extend(build_impls(cx, tcx, did).move_iter());
build_type(tcx, did)
}
// Assume that the enum type is reexported next to the variant, and
@ -193,7 +193,8 @@ fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
})
}
fn build_impls(tcx: &ty::ctxt,
fn build_impls(cx: &core::DocContext,
tcx: &ty::ctxt,
did: ast::DefId) -> Vec<clean::Item> {
ty::populate_implementations_for_type_if_necessary(tcx, did);
let mut impls = Vec::new();
@ -205,6 +206,38 @@ fn build_impls(tcx: &ty::ctxt,
}
}
// If this is the first time we've inlined something from this crate, then
// we inline *all* impls from the crate into this crate. Note that there's
// currently no way for us to filter this based on type, and we likely need
// many impls for a variety of reasons.
//
// Primarily, the impls will be used to populate the documentation for this
// type being inlined, but impls can also be used when generating
// documentation for primitives (no way to find those specifically).
if cx.populated_crate_impls.borrow_mut().insert(did.krate) {
csearch::each_top_level_item_of_crate(&tcx.sess.cstore,
did.krate,
|def, _, _| {
populate_impls(tcx, def, &mut impls)
});
fn populate_impls(tcx: &ty::ctxt,
def: decoder::DefLike,
impls: &mut Vec<clean::Item>) {
match def {
decoder::DlImpl(did) => impls.push(build_impl(tcx, did)),
decoder::DlDef(ast::DefMod(did)) => {
csearch::each_child_of_item(&tcx.sess.cstore,
did,
|def, _, _| {
populate_impls(tcx, def, impls)
})
}
_ => {}
}
}
}
impls
}
@ -268,7 +301,8 @@ fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
None => {}
}
}
decoder::DlImpl(did) => items.push(build_impl(tcx, did)),
// All impls were inlined above
decoder::DlImpl(..) => {}
decoder::DlField => fail!("unimplemented field"),
}
});

View File

@ -42,6 +42,7 @@ pub struct DocContext {
pub external_traits: RefCell<Option<HashMap<ast::DefId, clean::Trait>>>,
pub external_typarams: RefCell<Option<HashMap<ast::DefId, String>>>,
pub inlined: RefCell<Option<HashSet<ast::DefId>>>,
pub populated_crate_impls: RefCell<HashSet<ast::CrateNum>>,
}
impl DocContext {
@ -114,6 +115,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>)
external_typarams: RefCell::new(Some(HashMap::new())),
external_paths: RefCell::new(Some(HashMap::new())),
inlined: RefCell::new(Some(HashSet::new())),
populated_crate_impls: RefCell::new(HashSet::new()),
}, CrateAnalysis {
exported_items: exported_items,
public_items: public_items,

View File

@ -79,6 +79,7 @@ pub fn run(input: &str,
external_traits: RefCell::new(None),
external_typarams: RefCell::new(None),
inlined: RefCell::new(None),
populated_crate_impls: RefCell::new(HashSet::new()),
};
super::ctxtkey.replace(Some(ctx));