Skip to content

Commit 04ecf52

Browse files
authored
Rollup merge of rust-lang#94417 - GuillaumeGomez:fix-duplicated-impl-links, r=notriddle
Fix duplicated impl links Fixes rust-lang#78701. The problem is that the blanket impl has the same ID as the other impl, except that we don't derive IDs when we generate the sidebar. We now do. r? ``@notriddle``
2 parents c930884 + 9b8a6b9 commit 04ecf52

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

Diff for: src/librustdoc/html/render/mod.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ use crate::html::format::{
7474
PrintWithSpace,
7575
};
7676
use crate::html::highlight;
77-
use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine};
77+
use crate::html::markdown::{HeadingOffset, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine};
7878
use crate::html::sources;
7979
use crate::scrape_examples::{CallData, CallLocation};
8080
use crate::try_none;
@@ -1950,8 +1950,10 @@ fn small_url_encode(s: String) -> String {
19501950
fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
19511951
let did = it.def_id.expect_def_id();
19521952
let cache = cx.cache();
1953+
19531954
if let Some(v) = cache.impls.get(&did) {
19541955
let mut used_links = FxHashSet::default();
1956+
let mut id_map = IdMap::new();
19551957

19561958
{
19571959
let used_links_bor = &mut used_links;
@@ -1992,7 +1994,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
19921994
sidebar_deref_methods(cx, out, impl_, v, &mut derefs);
19931995
}
19941996

1995-
let format_impls = |impls: Vec<&Impl>| {
1997+
let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| {
19961998
let mut links = FxHashSet::default();
19971999

19982000
let mut ret = impls
@@ -2001,13 +2003,14 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
20012003
if let Some(ref i) = it.inner_impl().trait_ {
20022004
let i_display = format!("{:#}", i.print(cx));
20032005
let out = Escape(&i_display);
2004-
let encoded = small_url_encode(format!("{:#}", i.print(cx)));
2006+
let encoded =
2007+
id_map.derive(small_url_encode(format!("impl-{:#}", i.print(cx))));
20052008
let prefix = match it.inner_impl().polarity {
20062009
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
20072010
ty::ImplPolarity::Negative => "!",
20082011
};
20092012
let generated =
2010-
format!("<a href=\"#impl-{}\">{}{}</a>", encoded, prefix, out);
2013+
format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out);
20112014
if links.insert(generated.clone()) { Some(generated) } else { None }
20122015
} else {
20132016
None
@@ -2023,9 +2026,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
20232026
let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) =
20242027
concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket());
20252028

2026-
let concrete_format = format_impls(concrete);
2027-
let synthetic_format = format_impls(synthetic);
2028-
let blanket_format = format_impls(blanket_impl);
2029+
let concrete_format = format_impls(concrete, &mut id_map);
2030+
let synthetic_format = format_impls(synthetic, &mut id_map);
2031+
let blanket_format = format_impls(blanket_impl, &mut id_map);
20292032

20302033
if !concrete_format.is_empty() {
20312034
print_sidebar_block(

Diff for: src/test/rustdoc/issue-78701.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![crate_name = "foo"]
2+
3+
// This test ensures that if a blanket impl has the same ID as another impl, it'll
4+
// link to the blanket impl and not the other impl. Basically, we're checking if
5+
// the ID is correctly derived.
6+
7+
// @has 'foo/struct.AnotherStruct.html'
8+
// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait"]' 1
9+
// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait-1"]' 1
10+
11+
pub trait Something {}
12+
13+
pub trait AnAmazingTrait {}
14+
15+
impl<T: Something> AnAmazingTrait for T {}
16+
17+
pub struct AnotherStruct<T>(T);
18+
19+
impl<T: Something> Something for AnotherStruct<T> {}
20+
impl AnAmazingTrait for AnotherStruct<()> {}

0 commit comments

Comments
 (0)