Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix duplicated impl links #94417

Merged
merged 2 commits into from
Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ use crate::html::format::{
PrintWithSpace,
};
use crate::html::highlight;
use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine};
use crate::html::markdown::{HeadingOffset, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine};
use crate::html::sources;
use crate::scrape_examples::{CallData, CallLocation};
use crate::try_none;
Expand Down Expand Up @@ -1950,8 +1950,10 @@ fn small_url_encode(s: String) -> String {
fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
let did = it.def_id.expect_def_id();
let cache = cx.cache();

if let Some(v) = cache.impls.get(&did) {
let mut used_links = FxHashSet::default();
let mut id_map = IdMap::new();

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

let format_impls = |impls: Vec<&Impl>| {
let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| {
let mut links = FxHashSet::default();

let mut ret = impls
Expand All @@ -2001,13 +2003,14 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
if let Some(ref i) = it.inner_impl().trait_ {
let i_display = format!("{:#}", i.print(cx));
let out = Escape(&i_display);
let encoded = small_url_encode(format!("{:#}", i.print(cx)));
let encoded =
id_map.derive(small_url_encode(format!("impl-{:#}", i.print(cx))));
let prefix = match it.inner_impl().polarity {
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
ty::ImplPolarity::Negative => "!",
};
let generated =
format!("<a href=\"#impl-{}\">{}{}</a>", encoded, prefix, out);
format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out);
if links.insert(generated.clone()) { Some(generated) } else { None }
} else {
None
Expand All @@ -2023,9 +2026,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) =
concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket());

let concrete_format = format_impls(concrete);
let synthetic_format = format_impls(synthetic);
let blanket_format = format_impls(blanket_impl);
let concrete_format = format_impls(concrete, &mut id_map);
let synthetic_format = format_impls(synthetic, &mut id_map);
let blanket_format = format_impls(blanket_impl, &mut id_map);

if !concrete_format.is_empty() {
print_sidebar_block(
Expand Down
20 changes: 20 additions & 0 deletions src/test/rustdoc/issue-78701.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#![crate_name = "foo"]

// This test ensures that if a blanket impl has the same ID as another impl, it'll
// link to the blanket impl and not the other impl. Basically, we're checking if
// the ID is correctly derived.

// @has 'foo/struct.AnotherStruct.html'
// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait"]' 1
// @count - '//*[@class="sidebar"]//a[@href="#impl-AnAmazingTrait-1"]' 1

pub trait Something {}

pub trait AnAmazingTrait {}

impl<T: Something> AnAmazingTrait for T {}

pub struct AnotherStruct<T>(T);

impl<T: Something> Something for AnotherStruct<T> {}
impl AnAmazingTrait for AnotherStruct<()> {}