Skip to content

Commit e9cb96a

Browse files
committed
rustdoc: Don't inline all impls all at once
Right now whenever rustdoc inlines a struct or enum from another crate it ends up inlining *all* `impl` items found in the other crate at the same time. The rationale for this was to discover all trait impls which are otherwise not probed for. This unfortunately picks up a lot of impls of public traits for private types, causing lots of broken links. This commit instead hoards all of those inlined impls into a temporary storage location which is then selectively drawn from whenever we inline a new type. This should ensure that we still inline all relevant impls while avoiding all private ones.
1 parent 8aa268e commit e9cb96a

File tree

4 files changed

+30
-6
lines changed

4 files changed

+30
-6
lines changed

src/librustdoc/clean/inline.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,8 @@ fn build_type(cx: &DocContext, tcx: &TyCtxt, did: DefId) -> clean::ItemEnum {
222222
}, false)
223223
}
224224

225-
pub fn build_impls(cx: &DocContext, tcx: &TyCtxt,
225+
pub fn build_impls(cx: &DocContext,
226+
tcx: &TyCtxt,
226227
did: DefId) -> Vec<clean::Item> {
227228
tcx.populate_inherent_implementations_for_type_if_necessary(did);
228229
let mut impls = Vec::new();
@@ -241,10 +242,12 @@ pub fn build_impls(cx: &DocContext, tcx: &TyCtxt,
241242
// Primarily, the impls will be used to populate the documentation for this
242243
// type being inlined, but impls can also be used when generating
243244
// documentation for primitives (no way to find those specifically).
244-
if cx.populated_crate_impls.borrow_mut().insert(did.krate) {
245+
if !cx.all_crate_impls.borrow_mut().contains_key(&did.krate) {
246+
let mut impls = Vec::new();
245247
for item in tcx.sess.cstore.crate_top_level_items(did.krate) {
246248
populate_impls(cx, tcx, item.def, &mut impls);
247249
}
250+
cx.all_crate_impls.borrow_mut().insert(did.krate, impls);
248251

249252
fn populate_impls(cx: &DocContext, tcx: &TyCtxt,
250253
def: cstore::DefLike,
@@ -266,6 +269,20 @@ pub fn build_impls(cx: &DocContext, tcx: &TyCtxt,
266269
}
267270
}
268271

272+
let mut candidates = cx.all_crate_impls.borrow_mut();
273+
let candidates = candidates.get_mut(&did.krate).unwrap();
274+
for i in (0..candidates.len()).rev() {
275+
let remove = match candidates[i].inner {
276+
clean::ImplItem(ref i) => {
277+
i.for_.def_id() == Some(did) || i.for_.primitive_type().is_some()
278+
}
279+
_ => continue,
280+
};
281+
if remove {
282+
impls.push(candidates.swap_remove(i));
283+
}
284+
}
285+
269286
return impls;
270287
}
271288

src/librustdoc/clean/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,13 @@ impl Type {
14991499
_ => None,
15001500
}
15011501
}
1502+
1503+
fn def_id(&self) -> Option<DefId> {
1504+
match *self {
1505+
ResolvedPath { did, .. } => Some(did),
1506+
_ => None,
1507+
}
1508+
}
15021509
}
15031510

15041511
impl PrimitiveType {

src/librustdoc/core.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub struct DocContext<'a, 'tcx: 'a> {
5656
pub external_traits: RefCell<Option<HashMap<DefId, clean::Trait>>>,
5757
pub external_typarams: RefCell<Option<HashMap<DefId, String>>>,
5858
pub inlined: RefCell<Option<HashSet<DefId>>>,
59-
pub populated_crate_impls: RefCell<HashSet<ast::CrateNum>>,
59+
pub all_crate_impls: RefCell<HashMap<ast::CrateNum, Vec<clean::Item>>>,
6060
pub deref_trait_did: Cell<Option<DefId>>,
6161
}
6262

@@ -179,7 +179,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
179179
external_typarams: RefCell::new(Some(HashMap::new())),
180180
external_paths: RefCell::new(Some(HashMap::new())),
181181
inlined: RefCell::new(Some(HashSet::new())),
182-
populated_crate_impls: RefCell::new(HashSet::new()),
182+
all_crate_impls: RefCell::new(HashMap::new()),
183183
deref_trait_did: Cell::new(None),
184184
};
185185
debug!("crate: {:?}", ctxt.map.krate());

src/librustdoc/test.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#![allow(deprecated)]
1212

1313
use std::cell::{RefCell, Cell};
14-
use std::collections::{HashSet, HashMap};
14+
use std::collections::HashMap;
1515
use std::dynamic_lib::DynamicLibrary;
1616
use std::env;
1717
use std::ffi::OsString;
@@ -114,7 +114,7 @@ pub fn run(input: &str,
114114
external_traits: RefCell::new(None),
115115
external_typarams: RefCell::new(None),
116116
inlined: RefCell::new(None),
117-
populated_crate_impls: RefCell::new(HashSet::new()),
117+
all_crate_impls: RefCell::new(HashMap::new()),
118118
deref_trait_did: Cell::new(None),
119119
};
120120

0 commit comments

Comments
 (0)