diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f560350d510..1ce7c9cfc8a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -4234,13 +4234,30 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { } } -fn get_methods(i: &clean::Impl, for_deref: bool) -> Vec { +fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { + if used_links.insert(url.clone()) { + return url; + } + let mut add = 1; + while used_links.insert(format!("{}-{}", url, add)) == false { + add += 1; + } + format!("{}-{}", url, add) +} + +fn get_methods( + i: &clean::Impl, + for_deref: bool, + used_links: &mut FxHashSet, +) -> Vec { i.items.iter().filter_map(|item| { match item.name { // Maybe check with clean::Visibility::Public as well? Some(ref name) if !name.is_empty() && item.visibility.is_some() && item.is_method() => { if !for_deref || should_render_item(item, false) { - Some(format!("{name}", name = name)) + Some(format!("{}", + get_next_url(used_links, format!("method.{}", name)), + name)) } else { None } @@ -4270,13 +4287,20 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { let mut out = String::new(); let c = cache(); if let Some(v) = c.impls.get(&it.def_id) { - let ret = v.iter() - .filter(|i| i.inner_impl().trait_.is_none()) - .flat_map(|i| get_methods(i.inner_impl(), false)) - .collect::(); - if !ret.is_empty() { - out.push_str(&format!("Methods\ -
{}
", ret)); + let mut used_links = FxHashSet::default(); + + { + let used_links_bor = Rc::new(RefCell::new(&mut used_links)); + let ret = v.iter() + .filter(|i| i.inner_impl().trait_.is_none()) + .flat_map(move |i| get_methods(i.inner_impl(), + false, + &mut used_links_bor.borrow_mut())) + .collect::(); + if !ret.is_empty() { + out.push_str(&format!("Methods\ +
{}
", ret)); + } } if v.iter().any(|i| i.inner_impl().trait_.is_some()) { @@ -4301,7 +4325,9 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { out.push_str(""); let ret = impls.iter() .filter(|i| i.inner_impl().trait_.is_none()) - .flat_map(|i| get_methods(i.inner_impl(), true)) + .flat_map(|i| get_methods(i.inner_impl(), + true, + &mut used_links)) .collect::(); out.push_str(&format!("
{}
", ret)); } @@ -4309,27 +4335,28 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { } let format_impls = |impls: Vec<&Impl>| { let mut links = FxHashSet::default(); + impls.iter() - .filter_map(|i| { - let is_negative_impl = is_negative_impl(i.inner_impl()); - if let Some(ref i) = i.inner_impl().trait_ { - let i_display = format!("{:#}", i); - let out = Escape(&i_display); - let encoded = small_url_encode(&format!("{:#}", i)); - let generated = format!("{}{}", - encoded, - if is_negative_impl { "!" } else { "" }, - out); - if links.insert(generated.clone()) { - Some(generated) - } else { - None - } - } else { - None - } - }) - .collect::() + .filter_map(|i| { + let is_negative_impl = is_negative_impl(i.inner_impl()); + if let Some(ref i) = i.inner_impl().trait_ { + let i_display = format!("{:#}", i); + let out = Escape(&i_display); + let encoded = small_url_encode(&format!("{:#}", i)); + let generated = format!("{}{}", + encoded, + if is_negative_impl { "!" } else { "" }, + out); + if links.insert(generated.clone()) { + Some(generated) + } else { + None + } + } else { + None + } + }) + .collect::() }; let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = v