From 6bdfd12ee9f09c48e7ec00403d5be10d3b7b6b2c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 14 Dec 2024 14:45:30 -0800 Subject: [PATCH] Suppress `= _` on associated constants in impls --- src/librustdoc/html/render/mod.rs | 50 +++++++++++++++++++----- tests/rustdoc/assoc-consts-underscore.rs | 9 +++-- tests/rustdoc/bold-tag-101743.rs | 2 +- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 4d9faf2f568..436b5422ba9 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -835,12 +835,23 @@ fn assoc_href_attr(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>) href.map(|href| format!(" href=\"{href}\"")).unwrap_or_default() } +#[derive(Debug)] +enum AssocConstValue<'a> { + // In trait definitions, it is relevant for the public API whether an + // associated constant comes with a default value, so even if we cannot + // render its value, the presence of a value must be shown using `= _`. + TraitDefault(&'a clean::ConstantKind), + // In impls, there is no need to show `= _`. + Impl(&'a clean::ConstantKind), + None, +} + fn assoc_const( w: &mut Buffer, it: &clean::Item, generics: &clean::Generics, ty: &clean::Type, - default: Option<&clean::ConstantKind>, + value: AssocConstValue<'_>, link: AssocItemLink<'_>, indent: usize, cx: &Context<'_>, @@ -856,15 +867,20 @@ fn assoc_const( generics = generics.print(cx), ty = ty.print(cx), ); - if let Some(default) = default { - w.write_str(" = "); - + if let AssocConstValue::TraitDefault(konst) | AssocConstValue::Impl(konst) = value { // FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the // hood which adds noisy underscores and a type suffix to number literals. // This hurts readability in this context especially when more complex expressions // are involved and it doesn't add much of value. // Find a way to print constants here without all that jazz. - write!(w, "{}", Escape(&default.value(tcx).unwrap_or_else(|| default.expr(tcx)))); + let repr = konst.value(tcx).unwrap_or_else(|| konst.expr(tcx)); + if match value { + AssocConstValue::TraitDefault(_) => true, // always show + AssocConstValue::Impl(_) => repr != "_", // show if there is a meaningful value to show + AssocConstValue::None => unreachable!(), + } { + write!(w, " = {}", Escape(&repr)); + } } write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline)); } @@ -1086,17 +1102,27 @@ fn render_assoc_item( item, generics, ty, - None, + AssocConstValue::None, link, if parent == ItemType::Trait { 4 } else { 0 }, cx, ), - clean::ProvidedAssocConstItem(ci) | clean::ImplAssocConstItem(ci) => assoc_const( + clean::ProvidedAssocConstItem(ci) => assoc_const( w, item, &ci.generics, &ci.type_, - Some(&ci.kind), + AssocConstValue::TraitDefault(&ci.kind), + link, + if parent == ItemType::Trait { 4 } else { 0 }, + cx, + ), + clean::ImplAssocConstItem(ci) => assoc_const( + w, + item, + &ci.generics, + &ci.type_, + AssocConstValue::Impl(&ci.kind), link, if parent == ItemType::Trait { 4 } else { 0 }, cx, @@ -1704,7 +1730,7 @@ fn render_impl( item, generics, ty, - None, + AssocConstValue::None, link.anchor(if trait_.is_some() { &source_id } else { &id }), 0, cx, @@ -1726,7 +1752,11 @@ fn render_impl( item, &ci.generics, &ci.type_, - Some(&ci.kind), + match item.kind { + clean::ProvidedAssocConstItem(_) => AssocConstValue::TraitDefault(&ci.kind), + clean::ImplAssocConstItem(_) => AssocConstValue::Impl(&ci.kind), + _ => unreachable!(), + }, link.anchor(if trait_.is_some() { &source_id } else { &id }), 0, cx, diff --git a/tests/rustdoc/assoc-consts-underscore.rs b/tests/rustdoc/assoc-consts-underscore.rs index 9bb44f0a03c..f48098094db 100644 --- a/tests/rustdoc/assoc-consts-underscore.rs +++ b/tests/rustdoc/assoc-consts-underscore.rs @@ -14,14 +14,17 @@ pub trait Trait { } impl Trait for Struct { - //@ has assoc_consts_underscore/struct.Struct.html '//*[@id="associatedconstant.REQUIRED"]' \ + //@ !has assoc_consts_underscore/struct.Struct.html '//*[@id="associatedconstant.REQUIRED"]' \ // 'const REQUIRED: Struct = _' + //@ has - '//*[@id="associatedconstant.REQUIRED"]' 'const REQUIRED: Struct' const REQUIRED: Struct = Struct { _private: () }; - //@ has - '//*[@id="associatedconstant.OPTIONAL"]' 'const OPTIONAL: Struct = _' + //@ !has - '//*[@id="associatedconstant.OPTIONAL"]' 'const OPTIONAL: Struct = _' + //@ has - '//*[@id="associatedconstant.OPTIONAL"]' 'const OPTIONAL: Struct' const OPTIONAL: Struct = Struct { _private: () }; } impl Struct { - //@ has - '//*[@id="associatedconstant.INHERENT"]' 'const INHERENT: Struct = _' + //@ !has - '//*[@id="associatedconstant.INHERENT"]' 'const INHERENT: Struct = _' + //@ has - '//*[@id="associatedconstant.INHERENT"]' 'const INHERENT: Struct' pub const INHERENT: Struct = Struct { _private: () }; } diff --git a/tests/rustdoc/bold-tag-101743.rs b/tests/rustdoc/bold-tag-101743.rs index a81767eeeeb..3cd4005a4fa 100644 --- a/tests/rustdoc/bold-tag-101743.rs +++ b/tests/rustdoc/bold-tag-101743.rs @@ -14,6 +14,6 @@ impl Repr { // If we change back to rendering the value of consts, check this doesn't add // a tag, but escapes correctly - //@ has foo/struct.Repr.html '//section[@id="associatedconstant.BASE"]/h4' '= _' + //@ !has foo/struct.Repr.html '//section[@id="associatedconstant.BASE"]/h4' '=' pub const BASE: IBig = base_as_ibig::(); }