Skip to content

Commit e8c0aeb

Browse files
committed
Auto merge of #32985 - caipre:rustdoc-disambiguate-impl-anchors, r=alexcrichton
rustdoc: Disambiguate anchors Closes #32890
2 parents 14f61c8 + 894caf8 commit e8c0aeb

File tree

2 files changed

+53
-14
lines changed

2 files changed

+53
-14
lines changed

src/librustdoc/html/render.rs

+26-14
Original file line numberDiff line numberDiff line change
@@ -1904,34 +1904,35 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
19041904
if t.items.is_empty() {
19051905
write!(w, "{{ }}")?;
19061906
} else {
1907+
// FIXME: we should be using a derived_id for the Anchors here
19071908
write!(w, "{{\n")?;
19081909
for t in &types {
19091910
write!(w, " ")?;
1910-
render_assoc_item(w, t, AssocItemLink::Anchor)?;
1911+
render_assoc_item(w, t, AssocItemLink::Anchor(None))?;
19111912
write!(w, ";\n")?;
19121913
}
19131914
if !types.is_empty() && !consts.is_empty() {
19141915
w.write_str("\n")?;
19151916
}
19161917
for t in &consts {
19171918
write!(w, " ")?;
1918-
render_assoc_item(w, t, AssocItemLink::Anchor)?;
1919+
render_assoc_item(w, t, AssocItemLink::Anchor(None))?;
19191920
write!(w, ";\n")?;
19201921
}
19211922
if !consts.is_empty() && !required.is_empty() {
19221923
w.write_str("\n")?;
19231924
}
19241925
for m in &required {
19251926
write!(w, " ")?;
1926-
render_assoc_item(w, m, AssocItemLink::Anchor)?;
1927+
render_assoc_item(w, m, AssocItemLink::Anchor(None))?;
19271928
write!(w, ";\n")?;
19281929
}
19291930
if !required.is_empty() && !provided.is_empty() {
19301931
w.write_str("\n")?;
19311932
}
19321933
for m in &provided {
19331934
write!(w, " ")?;
1934-
render_assoc_item(w, m, AssocItemLink::Anchor)?;
1935+
render_assoc_item(w, m, AssocItemLink::Anchor(None))?;
19351936
write!(w, " {{ ... }}\n")?;
19361937
}
19371938
write!(w, "}}")?;
@@ -1948,7 +1949,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
19481949
write!(w, "<h3 id='{id}' class='method stab {stab}'><code>",
19491950
id = id,
19501951
stab = m.stability_class())?;
1951-
render_assoc_item(w, m, AssocItemLink::Anchor)?;
1952+
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)))?;
19521953
write!(w, "</code>")?;
19531954
render_stability_since(w, m, t)?;
19541955
write!(w, "</h3>")?;
@@ -2045,7 +2046,8 @@ fn naive_assoc_href(it: &clean::Item, link: AssocItemLink) -> String {
20452046

20462047
let anchor = format!("#{}.{}", ty, name);
20472048
match link {
2048-
AssocItemLink::Anchor => anchor,
2049+
AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id),
2050+
AssocItemLink::Anchor(None) => anchor,
20492051
AssocItemLink::GotoSource(did, _) => {
20502052
href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
20512053
}
@@ -2120,7 +2122,8 @@ fn render_assoc_item(w: &mut fmt::Formatter,
21202122
let name = meth.name.as_ref().unwrap();
21212123
let anchor = format!("#{}.{}", shortty(meth), name);
21222124
let href = match link {
2123-
AssocItemLink::Anchor => anchor,
2125+
AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id),
2126+
AssocItemLink::Anchor(None) => anchor,
21242127
AssocItemLink::GotoSource(did, provided_methods) => {
21252128
// We're creating a link from an impl-item to the corresponding
21262129
// trait-item and need to map the anchored type accordingly.
@@ -2381,10 +2384,19 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
23812384

23822385
#[derive(Copy, Clone)]
23832386
enum AssocItemLink<'a> {
2384-
Anchor,
2387+
Anchor(Option<&'a str>),
23852388
GotoSource(DefId, &'a HashSet<String>),
23862389
}
23872390

2391+
impl<'a> AssocItemLink<'a> {
2392+
fn anchor(&self, id: &'a String) -> Self {
2393+
match *self {
2394+
AssocItemLink::Anchor(_) => { AssocItemLink::Anchor(Some(&id)) },
2395+
ref other => *other,
2396+
}
2397+
}
2398+
}
2399+
23882400
enum AssocItemRender<'a> {
23892401
All,
23902402
DerefFor { trait_: &'a clean::Type, type_: &'a clean::Type },
@@ -2416,7 +2428,7 @@ fn render_assoc_items(w: &mut fmt::Formatter,
24162428
}
24172429
};
24182430
for i in &non_trait {
2419-
render_impl(w, cx, i, AssocItemLink::Anchor, render_header,
2431+
render_impl(w, cx, i, AssocItemLink::Anchor(None), render_header,
24202432
containing_item.stable_since())?;
24212433
}
24222434
}
@@ -2512,32 +2524,32 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
25122524
write!(w, "<h4 id='{}' class='{}'>", id, shortty)?;
25132525
render_stability_since_raw(w, item.stable_since(), outer_version)?;
25142526
write!(w, "<code>")?;
2515-
render_assoc_item(w, item, link)?;
2527+
render_assoc_item(w, item, link.anchor(&id))?;
25162528
write!(w, "</code></h4>\n")?;
25172529
}
25182530
}
25192531
clean::TypedefItem(ref tydef, _) => {
25202532
let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name));
25212533
write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
2522-
assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link)?;
2534+
assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?;
25232535
write!(w, "</code></h4>\n")?;
25242536
}
25252537
clean::AssociatedConstItem(ref ty, ref default) => {
25262538
let id = derive_id(format!("{}.{}", shortty, name));
25272539
write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
2528-
assoc_const(w, item, ty, default.as_ref(), link)?;
2540+
assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
25292541
write!(w, "</code></h4>\n")?;
25302542
}
25312543
clean::ConstantItem(ref c) => {
25322544
let id = derive_id(format!("{}.{}", shortty, name));
25332545
write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
2534-
assoc_const(w, item, &c.type_, Some(&c.expr), link)?;
2546+
assoc_const(w, item, &c.type_, Some(&c.expr), link.anchor(&id))?;
25352547
write!(w, "</code></h4>\n")?;
25362548
}
25372549
clean::AssociatedTypeItem(ref bounds, ref default) => {
25382550
let id = derive_id(format!("{}.{}", shortty, name));
25392551
write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
2540-
assoc_type(w, item, bounds, default.as_ref(), link)?;
2552+
assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?;
25412553
write!(w, "</code></h4>\n")?;
25422554
}
25432555
clean::StrippedItem(..) => return Ok(()),

src/test/rustdoc/issue-32890.rs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// @has issue_32890/struct.Foo.html
12+
pub struct Foo<T>(T);
13+
14+
impl Foo<u8> {
15+
// @has - '//a[@href="#method.pass"]' 'pass'
16+
pub fn pass() {}
17+
}
18+
19+
impl Foo<u16> {
20+
// @has - '//a[@href="#method.pass-1"]' 'pass'
21+
pub fn pass() {}
22+
}
23+
24+
impl Foo<u32> {
25+
// @has - '//a[@href="#method.pass-2"]' 'pass'
26+
pub fn pass() {}
27+
}

0 commit comments

Comments
 (0)