From 8c669d7f749a1f714e00eb4cdcac3a68e2208951 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 29 May 2014 01:35:44 -0700 Subject: [PATCH] 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. --- src/librustdoc/clean/inline.rs | 42 ++++++++++++++++++++++++++++++---- src/librustdoc/core.rs | 2 ++ src/librustdoc/test.rs | 1 + 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index b60e0a70dd0..0c2714355dc 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -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 { 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) { + 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"), } }); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 27e39e1235c..87b19fecb1f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -42,6 +42,7 @@ pub struct DocContext { pub external_traits: RefCell>>, pub external_typarams: RefCell>>, pub inlined: RefCell>>, + pub populated_crate_impls: RefCell>, } impl DocContext { @@ -114,6 +115,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet, cfgs: Vec) 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, diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index e5fc8f1f1a1..c1f61de9be2 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -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)); -- 2.44.0