Skip to content

Commit 8724337

Browse files
committed
Auto merge of #47039 - ollie27:rustdoc_trait_impl_src, r=GuillaumeGomez
rustdoc: Add missing src links for generic impls on trait pages `implementor2item` would return `None` for generic impls so instead this clones the entire `clean::Item` into the `implementors` map which simplifies some code.
2 parents 69f17d1 + 3d11d20 commit 8724337

File tree

2 files changed

+35
-60
lines changed

2 files changed

+35
-60
lines changed

src/librustdoc/html/render.rs

+30-60
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,7 @@ pub enum ExternalLocation {
173173
Unknown,
174174
}
175175

176-
/// Metadata about an implementor of a trait.
177-
pub struct Implementor {
178-
pub def_id: DefId,
179-
pub stability: Option<clean::Stability>,
180-
pub impl_: clean::Impl,
181-
}
182-
183-
/// Metadata about implementations for a type.
176+
/// Metadata about implementations for a type or trait.
184177
#[derive(Clone)]
185178
pub struct Impl {
186179
pub impl_item: clean::Item,
@@ -279,7 +272,7 @@ pub struct Cache {
279272
/// When rendering traits, it's often useful to be able to list all
280273
/// implementors of the trait, and this mapping is exactly, that: a mapping
281274
/// of trait ids to the list of known implementors of the trait
282-
pub implementors: FxHashMap<DefId, Vec<Implementor>>,
275+
pub implementors: FxHashMap<DefId, Vec<Impl>>,
283276

284277
/// Cache of where external crate documentation can be found.
285278
pub extern_locations: FxHashMap<CrateNum, (String, PathBuf, ExternalLocation)>,
@@ -971,12 +964,12 @@ fn write_shared(cx: &Context,
971964
// there's no need to emit information about it (there's inlining
972965
// going on). If they're in different crates then the crate defining
973966
// the trait will be interested in our implementation.
974-
if imp.def_id.krate == did.krate { continue }
967+
if imp.impl_item.def_id.krate == did.krate { continue }
975968
// If the implementation is from another crate then that crate
976969
// should add it.
977-
if !imp.def_id.is_local() { continue }
970+
if !imp.impl_item.def_id.is_local() { continue }
978971
have_impls = true;
979-
write!(implementors, "{},", as_json(&imp.impl_.to_string())).unwrap();
972+
write!(implementors, "{},", as_json(&imp.inner_impl().to_string())).unwrap();
980973
}
981974
implementors.push_str("];");
982975

@@ -1208,10 +1201,8 @@ impl DocFolder for Cache {
12081201
if !self.masked_crates.contains(&item.def_id.krate) {
12091202
if let Some(did) = i.trait_.def_id() {
12101203
if i.for_.def_id().map_or(true, |d| !self.masked_crates.contains(&d.krate)) {
1211-
self.implementors.entry(did).or_insert(vec![]).push(Implementor {
1212-
def_id: item.def_id,
1213-
stability: item.stability.clone(),
1214-
impl_: i.clone(),
1204+
self.implementors.entry(did).or_insert(vec![]).push(Impl {
1205+
impl_item: item.clone(),
12151206
});
12161207
}
12171208
}
@@ -2338,18 +2329,6 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
23382329
document(w, cx, it)
23392330
}
23402331

2341-
fn implementor2item<'a>(cache: &'a Cache, imp : &Implementor) -> Option<&'a clean::Item> {
2342-
if let Some(t_did) = imp.impl_.for_.def_id() {
2343-
if let Some(impl_item) = cache.impls.get(&t_did).and_then(|i| i.iter()
2344-
.find(|i| i.impl_item.def_id == imp.def_id))
2345-
{
2346-
let i = &impl_item.impl_item;
2347-
return Some(i);
2348-
}
2349-
}
2350-
None
2351-
}
2352-
23532332
fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
23542333
t: &clean::Trait) -> fmt::Result {
23552334
let mut bounds = String::new();
@@ -2533,7 +2512,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
25332512
// if any Types with the same name but different DefId have been found.
25342513
let mut implementor_dups: FxHashMap<&str, (DefId, bool)> = FxHashMap();
25352514
for implementor in implementors {
2536-
match implementor.impl_.for_ {
2515+
match implementor.inner_impl().for_ {
25372516
clean::ResolvedPath { ref path, did, is_generic: false, .. } |
25382517
clean::BorrowedRef {
25392518
type_: box clean::ResolvedPath { ref path, did, is_generic: false, .. },
@@ -2550,7 +2529,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
25502529
}
25512530

25522531
let (local, foreign) = implementors.iter()
2553-
.partition::<Vec<_>, _>(|i| i.impl_.for_.def_id()
2532+
.partition::<Vec<_>, _>(|i| i.inner_impl().for_.def_id()
25542533
.map_or(true, |d| cache.paths.contains_key(&d)));
25552534

25562535
if !foreign.is_empty() {
@@ -2561,42 +2540,37 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
25612540
")?;
25622541

25632542
for implementor in foreign {
2564-
if let Some(i) = implementor2item(&cache, implementor) {
2565-
let impl_ = Impl { impl_item: i.clone() };
2566-
let assoc_link = AssocItemLink::GotoSource(
2567-
i.def_id, &implementor.impl_.provided_trait_methods
2568-
);
2569-
render_impl(w, cx, &impl_, assoc_link,
2570-
RenderMode::Normal, i.stable_since(), false)?;
2571-
}
2543+
let assoc_link = AssocItemLink::GotoSource(
2544+
implementor.impl_item.def_id, &implementor.inner_impl().provided_trait_methods
2545+
);
2546+
render_impl(w, cx, &implementor, assoc_link,
2547+
RenderMode::Normal, implementor.impl_item.stable_since(), false)?;
25722548
}
25732549
}
25742550

25752551
write!(w, "{}", impl_header)?;
25762552

25772553
for implementor in local {
25782554
write!(w, "<li>")?;
2579-
if let Some(item) = implementor2item(&cache, implementor) {
2580-
if let Some(l) = (Item { cx, item }).src_href() {
2581-
write!(w, "<div class='out-of-band'>")?;
2582-
write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
2583-
l, "goto source code")?;
2584-
write!(w, "</div>")?;
2585-
}
2555+
if let Some(l) = (Item { cx, item: &implementor.impl_item }).src_href() {
2556+
write!(w, "<div class='out-of-band'>")?;
2557+
write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
2558+
l, "goto source code")?;
2559+
write!(w, "</div>")?;
25862560
}
25872561
write!(w, "<code>")?;
25882562
// If there's already another implementor that has the same abbridged name, use the
25892563
// full path, for example in `std::iter::ExactSizeIterator`
2590-
let use_absolute = match implementor.impl_.for_ {
2564+
let use_absolute = match implementor.inner_impl().for_ {
25912565
clean::ResolvedPath { ref path, is_generic: false, .. } |
25922566
clean::BorrowedRef {
25932567
type_: box clean::ResolvedPath { ref path, is_generic: false, .. },
25942568
..
25952569
} => implementor_dups[path.last_name()].1,
25962570
_ => false,
25972571
};
2598-
fmt_impl_for_trait_page(&implementor.impl_, w, use_absolute)?;
2599-
for it in &implementor.impl_.items {
2572+
fmt_impl_for_trait_page(&implementor.inner_impl(), w, use_absolute)?;
2573+
for it in &implementor.inner_impl().items {
26002574
if let clean::TypedefItem(ref tydef, _) = it.inner {
26012575
write!(w, "<span class=\"where fmt-newline\"> ")?;
26022576
assoc_type(w, it, &vec![], Some(&tydef.type_), AssocItemLink::Anchor(None))?;
@@ -3886,20 +3860,16 @@ fn sidebar_trait(fmt: &mut fmt::Formatter, it: &clean::Item,
38863860

38873861
if let Some(implementors) = c.implementors.get(&it.def_id) {
38883862
let res = implementors.iter()
3889-
.filter(|i| i.impl_.for_.def_id()
3890-
.map_or(false, |d| !c.paths.contains_key(&d)))
3863+
.filter(|i| i.inner_impl().for_.def_id()
3864+
.map_or(false, |d| !c.paths.contains_key(&d)))
38913865
.filter_map(|i| {
3892-
if let Some(item) = implementor2item(&c, i) {
3893-
match extract_for_impl_name(&item) {
3894-
Some((ref name, ref url)) => {
3895-
Some(format!("<a href=\"#impl-{}\">{}</a>",
3896-
small_url_encode(url),
3897-
Escape(name)))
3898-
}
3899-
_ => None,
3866+
match extract_for_impl_name(&i.impl_item) {
3867+
Some((ref name, ref url)) => {
3868+
Some(format!("<a href=\"#impl-{}\">{}</a>",
3869+
small_url_encode(url),
3870+
Escape(name)))
39003871
}
3901-
} else {
3902-
None
3872+
_ => None,
39033873
}
39043874
})
39053875
.collect::<String>();

src/test/rustdoc/issue-43893.rs

+5
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,8 @@ impl SomeTrait for usize {}
2222
impl SomeTrait for SomeStruct {
2323
// deliberately multi-line impl
2424
}
25+
26+
pub trait AnotherTrait {}
27+
28+
// @has foo/trait.AnotherTrait.html '//a/@href' '../src/foo/issue-43893.rs.html#29'
29+
impl<T> AnotherTrait for T {}

0 commit comments

Comments
 (0)