diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 24b84212a89..462cef2e0e3 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2021,10 +2021,33 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, Ok(()) } -fn assoc_const(w: &mut fmt::Formatter, it: &clean::Item, - ty: &clean::Type, default: Option<&String>) - -> fmt::Result { - write!(w, "const {}", it.name.as_ref().unwrap())?; +fn naive_assoc_href(it: &clean::Item, link: AssocItemLink) -> String { + use html::item_type::ItemType::*; + + let name = it.name.as_ref().unwrap(); + let ty = match shortty(it) { + Typedef | AssociatedType => AssociatedType, + s@_ => s, + }; + + let anchor = format!("#{}.{}", ty, name); + match link { + AssocItemLink::Anchor => anchor, + AssocItemLink::GotoSource(did, _) => { + href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor) + } + } +} + +fn assoc_const(w: &mut fmt::Formatter, + it: &clean::Item, + ty: &clean::Type, + default: Option<&String>, + link: AssocItemLink) -> fmt::Result { + write!(w, "const {}", + naive_assoc_href(it, link), + it.name.as_ref().unwrap())?; + write!(w, ": {}", ty)?; if let Some(default) = default { write!(w, " = {}", default)?; @@ -2034,13 +2057,15 @@ fn assoc_const(w: &mut fmt::Formatter, it: &clean::Item, fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item, bounds: &Vec, - default: &Option) - -> fmt::Result { - write!(w, "type {}", it.name.as_ref().unwrap())?; + default: Option<&clean::Type>, + link: AssocItemLink) -> fmt::Result { + write!(w, "type {}", + naive_assoc_href(it, link), + it.name.as_ref().unwrap())?; if !bounds.is_empty() { write!(w, ": {}", TyParamBounds(bounds))? } - if let Some(ref default) = *default { + if let Some(default) = default { write!(w, " = {}", default)?; } Ok(()) @@ -2095,6 +2120,7 @@ fn render_assoc_item(w: &mut fmt::Formatter, href(did).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor) } }; + // FIXME(#24111): remove when `const_fn` is stabilized let vis_constness = match get_unstable_features_setting() { UnstableFeatures::Allow => constness, _ => hir::Constness::NotConst @@ -2124,10 +2150,10 @@ fn render_assoc_item(w: &mut fmt::Formatter, link) } clean::AssociatedConstItem(ref ty, ref default) => { - assoc_const(w, item, ty, default.as_ref()) + assoc_const(w, item, ty, default.as_ref(), link) } clean::AssociatedTypeItem(ref bounds, ref default) => { - assoc_type(w, item, bounds, default) + assoc_type(w, item, bounds, default.as_ref(), link) } _ => panic!("render_assoc_item called on non-associated-item") } @@ -2487,25 +2513,25 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi clean::TypedefItem(ref tydef, _) => { let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name)); write!(w, "

", id, shortty)?; - write!(w, "type {} = {}", name, tydef.type_)?; + assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link)?; write!(w, "

\n")?; } clean::AssociatedConstItem(ref ty, ref default) => { let id = derive_id(format!("{}.{}", shortty, name)); write!(w, "

", id, shortty)?; - assoc_const(w, item, ty, default.as_ref())?; + assoc_const(w, item, ty, default.as_ref(), link)?; write!(w, "

\n")?; } clean::ConstantItem(ref c) => { let id = derive_id(format!("{}.{}", shortty, name)); write!(w, "

", id, shortty)?; - assoc_const(w, item, &c.type_, Some(&c.expr))?; + assoc_const(w, item, &c.type_, Some(&c.expr), link)?; write!(w, "

\n")?; } clean::AssociatedTypeItem(ref bounds, ref default) => { let id = derive_id(format!("{}.{}", shortty, name)); write!(w, "

", id, shortty)?; - assoc_type(w, item, bounds, default)?; + assoc_type(w, item, bounds, default.as_ref(), link)?; write!(w, "

\n")?; } _ => panic!("can't make docs for trait item with name {:?}", item.name) @@ -2545,9 +2571,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi } // If we've implemented a trait, then also emit documentation for all - // default methods which weren't overridden in the implementation block. - // FIXME: this also needs to be done for associated types, whenever defaults - // for them work. + // default items which weren't overridden in the implementation block. if let Some(did) = i.trait_did() { if let Some(t) = cache().traits.get(&did) { render_default_items(w, cx, t, &i.impl_, render_header, outer_version)?; diff --git a/src/test/rustdoc/issue-28478.rs b/src/test/rustdoc/issue-28478.rs index 9d3433fb399..0db92a491ed 100644 --- a/src/test/rustdoc/issue-28478.rs +++ b/src/test/rustdoc/issue-28478.rs @@ -14,9 +14,10 @@ // @has issue_28478/trait.Bar.html pub trait Bar { // @has - '//*[@id="associatedtype.Bar"]' 'type Bar = ()' + // @has - '//*[@href="#associatedtype.Bar"]' 'Bar' type Bar = (); - // @has - '//*[@id="associatedconstant.Baz"]' 'const Baz: usize = 7' + // @has - '//*[@href="#associatedconstant.Baz"]' 'Baz' const Baz: usize = 7; // @has - '//*[@id="tymethod.bar"]' 'fn bar' fn bar(); @@ -33,6 +34,8 @@ impl Foo { } impl Bar for Foo { + // @has - '//*[@href="../issue_28478/trait.Bar.html#associatedtype.Bar"]' 'Bar' + // @has - '//*[@href="../issue_28478/trait.Bar.html#associatedconstant.Baz"]' 'Baz' // @has - '//*[@href="../issue_28478/trait.Bar.html#tymethod.bar"]' 'bar' fn bar() {} // @has - '//*[@href="../issue_28478/trait.Bar.html#method.baz"]' 'baz'