diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index dc5aec3b084f5..69c5c2c4abc2a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1811,23 +1811,53 @@ fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { format!("{}-{}", url, add) } +struct SidebarLink { + name: Symbol, + url: String, +} + +impl fmt::Display for SidebarLink { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.url, self.name) + } +} + +impl PartialEq for SidebarLink { + fn eq(&self, other: &Self) -> bool { + self.url == other.url + } +} + +impl Eq for SidebarLink {} + +impl PartialOrd for SidebarLink { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for SidebarLink { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.url.cmp(&other.url) + } +} + fn get_methods( i: &clean::Impl, for_deref: bool, used_links: &mut FxHashSet, deref_mut: bool, tcx: TyCtxt<'_>, -) -> Vec { +) -> Vec { i.items .iter() .filter_map(|item| match item.name { - Some(ref name) if !name.is_empty() && item.is_method() => { + Some(name) if !name.is_empty() && item.is_method() => { if !for_deref || should_render_item(item, deref_mut, tcx) { - Some(format!( - "{}", - get_next_url(used_links, format!("method.{}", name)), - name - )) + Some(SidebarLink { + name, + url: get_next_url(used_links, format!("method.{}", name)), + }) } else { None } @@ -1837,6 +1867,22 @@ fn get_methods( .collect::>() } +fn get_associated_constants( + i: &clean::Impl, + used_links: &mut FxHashSet, +) -> Vec { + i.items + .iter() + .filter_map(|item| match item.name { + Some(name) if !name.is_empty() && item.is_associated_const() => Some(SidebarLink { + name, + url: get_next_url(used_links, format!("associatedconstant.{}", name)), + }), + _ => None, + }) + .collect::>() +} + // The point is to url encode any potential character from a type with genericity. fn small_url_encode(s: String) -> String { let mut st = String::new(); @@ -1881,23 +1927,40 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { { let used_links_bor = &mut used_links; - let mut ret = v + let mut assoc_consts = v + .iter() + .flat_map(|i| get_associated_constants(i.inner_impl(), used_links_bor)) + .collect::>(); + if !assoc_consts.is_empty() { + // We want links' order to be reproducible so we don't use unstable sort. + assoc_consts.sort(); + + out.push_str( + "

\ + Associated Constants\ +

\ +
", + ); + for line in assoc_consts { + write!(out, "{}", line); + } + out.push_str("
"); + } + let mut methods = v .iter() .filter(|i| i.inner_impl().trait_.is_none()) - .flat_map(move |i| { - get_methods(i.inner_impl(), false, used_links_bor, false, cx.tcx()) - }) + .flat_map(|i| get_methods(i.inner_impl(), false, used_links_bor, false, cx.tcx())) .collect::>(); - if !ret.is_empty() { + if !methods.is_empty() { // We want links' order to be reproducible so we don't use unstable sort. - ret.sort(); + methods.sort(); out.push_str( "

Methods

\
", ); - for line in ret { - out.push_str(&line); + for line in methods { + write!(out, "{}", line); } out.push_str("
"); } @@ -2032,7 +2095,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V ret.sort(); out.push_str("
"); for link in ret { - out.push_str(&link); + write!(out, "{}", link); } out.push_str("
"); } diff --git a/src/test/rustdoc/associated-consts.rs b/src/test/rustdoc/associated-consts.rs new file mode 100644 index 0000000000000..6ae5e20632e52 --- /dev/null +++ b/src/test/rustdoc/associated-consts.rs @@ -0,0 +1,31 @@ +#![crate_name = "foo"] + +pub trait Trait { + const FOO: u32 = 12; + + fn foo(); +} + +pub struct Bar; + +// @has 'foo/struct.Bar.html' +// @has - '//h3[@class="sidebar-title"]' 'Associated Constants' +// @has - '//div[@class="sidebar-elems"]//div[@class="sidebar-links"]/a' 'FOO' +impl Trait for Bar { + const FOO: u32 = 1; + + fn foo() {} +} + +pub enum Foo { + A, +} + +// @has 'foo/enum.Foo.html' +// @has - '//h3[@class="sidebar-title"]' 'Associated Constants' +// @has - '//div[@class="sidebar-elems"]//div[@class="sidebar-links"]/a' 'FOO' +impl Trait for Foo { + const FOO: u32 = 1; + + fn foo() {} +}