Rollup merge of #94417 - GuillaumeGomez:fix-duplicated-impl-links, r=notriddle
Fix duplicated impl links Fixes #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``
This commit is contained in:
commit
04ecf52a48
2 changed files with 30 additions and 7 deletions
src
|
@ -74,7 +74,7 @@ use crate::html::format::{
|
||||||
PrintWithSpace,
|
PrintWithSpace,
|
||||||
};
|
};
|
||||||
use crate::html::highlight;
|
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::html::sources;
|
||||||
use crate::scrape_examples::{CallData, CallLocation};
|
use crate::scrape_examples::{CallData, CallLocation};
|
||||||
use crate::try_none;
|
use crate::try_none;
|
||||||
|
@ -1950,8 +1950,10 @@ fn small_url_encode(s: String) -> String {
|
||||||
fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||||
let did = it.def_id.expect_def_id();
|
let did = it.def_id.expect_def_id();
|
||||||
let cache = cx.cache();
|
let cache = cx.cache();
|
||||||
|
|
||||||
if let Some(v) = cache.impls.get(&did) {
|
if let Some(v) = cache.impls.get(&did) {
|
||||||
let mut used_links = FxHashSet::default();
|
let mut used_links = FxHashSet::default();
|
||||||
|
let mut id_map = IdMap::new();
|
||||||
|
|
||||||
{
|
{
|
||||||
let used_links_bor = &mut used_links;
|
let used_links_bor = &mut used_links;
|
||||||
|
@ -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);
|
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 links = FxHashSet::default();
|
||||||
|
|
||||||
let mut ret = impls
|
let mut ret = impls
|
||||||
|
@ -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_ {
|
if let Some(ref i) = it.inner_impl().trait_ {
|
||||||
let i_display = format!("{:#}", i.print(cx));
|
let i_display = format!("{:#}", i.print(cx));
|
||||||
let out = Escape(&i_display);
|
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 {
|
let prefix = match it.inner_impl().polarity {
|
||||||
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
|
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
|
||||||
ty::ImplPolarity::Negative => "!",
|
ty::ImplPolarity::Negative => "!",
|
||||||
};
|
};
|
||||||
let generated =
|
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 }
|
if links.insert(generated.clone()) { Some(generated) } else { None }
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -2023,9 +2026,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||||
let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
||||||
concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket());
|
concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket());
|
||||||
|
|
||||||
let concrete_format = format_impls(concrete);
|
let concrete_format = format_impls(concrete, &mut id_map);
|
||||||
let synthetic_format = format_impls(synthetic);
|
let synthetic_format = format_impls(synthetic, &mut id_map);
|
||||||
let blanket_format = format_impls(blanket_impl);
|
let blanket_format = format_impls(blanket_impl, &mut id_map);
|
||||||
|
|
||||||
if !concrete_format.is_empty() {
|
if !concrete_format.is_empty() {
|
||||||
print_sidebar_block(
|
print_sidebar_block(
|
||||||
|
|
20
src/test/rustdoc/issue-78701.rs
Normal file
20
src/test/rustdoc/issue-78701.rs
Normal file
|
@ -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<()> {}
|
Loading…
Add table
Reference in a new issue