diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 63de870f07f45..e6fca29e23e5f 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1050,14 +1050,11 @@ fn assoc_const(
ty = print_type(ty, cx),
)?;
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.
- let repr = konst.value(tcx).unwrap_or_else(|| konst.expr(tcx));
+ let repr = konst.expr(tcx);
if match value {
AssocConstValue::TraitDefault(_) => true, // always show
+ // FIXME: Comparing against the special string "_" denoting overly complex const exprs
+ // is rather hacky; `ConstKind::expr` should have a richer return type.
AssocConstValue::Impl(_) => repr != "_", // show if there is a meaningful value to show
AssocConstValue::None => unreachable!(),
} {
diff --git a/tests/rustdoc-html/anchors/anchors.no_const_anchor2.html b/tests/rustdoc-html/anchors/anchors.no_const_anchor2.html
index 091dac3e4b261..310957ac1ae05 100644
--- a/tests/rustdoc-html/anchors/anchors.no_const_anchor2.html
+++ b/tests/rustdoc-html/anchors/anchors.no_const_anchor2.html
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/tests/rustdoc-html/attributes.rs b/tests/rustdoc-html/attributes.rs
index 429a42a7252cd..6032c3d388011 100644
--- a/tests/rustdoc-html/attributes.rs
+++ b/tests/rustdoc-html/attributes.rs
@@ -59,7 +59,7 @@ pub enum Enum {
pub trait Trait {
//@ has 'foo/trait.Trait.html'
//@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]/*[@class="code-attribute"]' '#[unsafe(link_section = "bar")]'
- //@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' 'const BAR: u32 = 0u32'
+ //@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' 'const BAR: u32 = 0'
#[unsafe(link_section = "bar")]
const BAR: u32 = 0;
diff --git a/tests/rustdoc-html/constant/assoc-const-has-projection-ty.rs b/tests/rustdoc-html/constant/assoc-const-has-projection-ty.rs
new file mode 100644
index 0000000000000..ed0789dade574
--- /dev/null
+++ b/tests/rustdoc-html/constant/assoc-const-has-projection-ty.rs
@@ -0,0 +1,31 @@
+// Ensure that we properly print the value `1` as `1` in the initializer of associated constants
+// that have user type "projection".
+//
+// We once used to evaluate the initializer in rustdoc and use rustc's MIR pretty-printer to
+// render the resulting MIR const value. This pretty printer matches on the type to interpret
+// the data and falls back to a cryptic `"{transmute(0x$data): $ty}"` for types it can't handle.
+// Crucially, when constructing the MIR const we passed the unnormalized type of the initializer,
+// i.e., the projection `::Ty` instead of the normalized `u32` which the
+// pretty printer obviously can't handle.
+//
+// Now we no longer evaluate it and use a custom printer for the const expr.
+//
+// issue:
+
+#![crate_name = "it"]
+
+pub trait Trait {
+ type Ty;
+
+ const CT: Self::Ty;
+}
+
+pub struct Struct;
+
+impl Trait for Struct {
+ type Ty = u32;
+
+ //@ has it/struct.Struct.html
+ //@ has - '//*[@id="associatedconstant.CT"]' 'const CT: Self::Ty = 1'
+ const CT: Self::Ty = 1;
+}
diff --git a/tests/rustdoc-html/constant/assoc-consts.rs b/tests/rustdoc-html/constant/assoc-consts.rs
index 247b5b180a869..0994ec7517e3e 100644
--- a/tests/rustdoc-html/constant/assoc-consts.rs
+++ b/tests/rustdoc-html/constant/assoc-consts.rs
@@ -1,6 +1,6 @@
pub trait Foo {
//@ has assoc_consts/trait.Foo.html '//pre[@class="rust item-decl"]' \
- // 'const FOO: usize = 13usize;'
+ // 'const FOO: usize = _;'
//@ has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize'
const FOO: usize = 12 + 1;
//@ has - '//*[@id="associatedconstant.FOO_NO_DEFAULT"]' 'const FOO_NO_DEFAULT: bool'
diff --git a/tests/rustdoc-html/deref/deref-to-primitive.rs b/tests/rustdoc-html/deref/deref-to-primitive.rs
index 7a5a3cd8fd655..6fdc382b2213b 100644
--- a/tests/rustdoc-html/deref/deref-to-primitive.rs
+++ b/tests/rustdoc-html/deref/deref-to-primitive.rs
@@ -3,7 +3,7 @@
//@ has 'foo/struct.Foo.html'
//@ has - '//*[@id="deref-methods-i32"]' 'Methods from Deref'
//@ has - '//*[@id="deref-methods-i32-1"]//*[@id="associatedconstant.BITS"]/h4' \
-// 'pub const BITS: u32 = 32u32'
+// 'pub const BITS: u32 = u32::BITS'
pub struct Foo(i32);
impl std::ops::Deref for Foo {
diff --git a/tests/rustdoc-html/display-hidden-items.rs b/tests/rustdoc-html/display-hidden-items.rs
index 40cd636e2fe29..8b0854d1ade81 100644
--- a/tests/rustdoc-html/display-hidden-items.rs
+++ b/tests/rustdoc-html/display-hidden-items.rs
@@ -20,7 +20,7 @@ pub trait TraitHidden {}
//@ has 'foo/index.html' '//dt/a[@class="trait"]' 'Trait'
pub trait Trait {
//@ has 'foo/trait.Trait.html'
- //@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' '#[doc(hidden)] const BAR: u32 = 0u32'
+ //@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' '#[doc(hidden)] const BAR: u32 = 0'
#[doc(hidden)]
const BAR: u32 = 0;
@@ -44,7 +44,7 @@ impl Struct {
}
impl Trait for Struct {
- //@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' '#[doc(hidden)] const BAR: u32 = 0u32'
+ //@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' '#[doc(hidden)] const BAR: u32 = 0'
//@ has - '//*[@id="method.foo"]/*[@class="code-header"]' '#[doc(hidden)] fn foo()'
}
//@ has - '//*[@id="impl-TraitHidden-for-Struct"]/*[@class="code-header"]' 'impl TraitHidden for Struct'
diff --git a/tests/rustdoc-html/impl/impl-associated-items-order.rs b/tests/rustdoc-html/impl/impl-associated-items-order.rs
index 759e0f0b40095..3f1d047201636 100644
--- a/tests/rustdoc-html/impl/impl-associated-items-order.rs
+++ b/tests/rustdoc-html/impl/impl-associated-items-order.rs
@@ -16,7 +16,7 @@ impl Bar {
// 'pub fn foo()'
pub fn foo() {}
//@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[1]/h4' \
- // 'pub const X: u8 = 12u8'
+ // 'pub const X: u8 = 12'
pub const X: u8 = 12;
//@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[2]/h4' \
// 'pub type Y = u8'
@@ -34,7 +34,7 @@ impl Foo for Bar {
// 'type Z = u8'
type Z = u8;
//@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[1]/h4' \
- // 'const W: u32 = 12u32'
+ // 'const W: u32 = 12'
const W: u32 = 12;
//@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[3]/h4' \
// 'fn yeay()'
diff --git a/tests/rustdoc-ui/diverging-assoc-consts.rs b/tests/rustdoc-ui/diverging-assoc-consts.rs
new file mode 100644
index 0000000000000..fd0a177e7c4b8
--- /dev/null
+++ b/tests/rustdoc-ui/diverging-assoc-consts.rs
@@ -0,0 +1,33 @@
+// Ensure that we don't unconditionally evaluate the initializer of associated constants.
+//
+// We once used to evaluate them so we could display more kinds of expressions
+// (like `1 + 1` as `2`) given the fact that we generally only want to render
+// literals (otherwise we would risk dumping extremely large exprs or leaking
+// private struct fields).
+//
+// However, that deviated from rustc's behavior, made rustdoc accept less code
+// and was understandably surprising to users. So let's not.
+//
+// In the future we *might* provide users a mechanism to control this behavior.
+// E.g., via a new `#[doc(...)]` attribute.
+//
+// See also:
+// issue:
+// issue:
+
+//@ check-pass
+
+pub struct Type;
+
+impl Type {
+ pub const K0: () = panic!();
+ pub const K1: std::convert::Infallible = loop {};
+}
+
+pub trait Trait {
+ const K2: i32 = panic!();
+}
+
+impl Trait for Type {
+ const K2: i32 = loop {};
+}