Skip to content

Commit fe98ddc

Browse files
committed
Auto merge of #151232 - fmease:rustdoc-dont-eval-assoc-consts, r=yotamofek
rustdoc: Stop unconditionally evaluating the initializer of associated consts See the descriptions of the added tests for details. Fixes #131625. Fixes [after beta-1.93 backport] #149635. Fixes #150312. Supersedes #150629 IINM. CC @cuviper (#149635 (comment)) r? @GuillaumeGomez or @yotamofek (#150629)
2 parents 9f6cd6d + ac8e850 commit fe98ddc

9 files changed

Lines changed: 75 additions & 14 deletions

File tree

src/librustdoc/html/render/mod.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,14 +1050,11 @@ fn assoc_const(
10501050
ty = print_type(ty, cx),
10511051
)?;
10521052
if let AssocConstValue::TraitDefault(konst) | AssocConstValue::Impl(konst) = value {
1053-
// FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the
1054-
// hood which adds noisy underscores and a type suffix to number literals.
1055-
// This hurts readability in this context especially when more complex expressions
1056-
// are involved and it doesn't add much of value.
1057-
// Find a way to print constants here without all that jazz.
1058-
let repr = konst.value(tcx).unwrap_or_else(|| konst.expr(tcx));
1053+
let repr = konst.expr(tcx);
10591054
if match value {
10601055
AssocConstValue::TraitDefault(_) => true, // always show
1056+
// FIXME: Comparing against the special string "_" denoting overly complex const exprs
1057+
// is rather hacky; `ConstKind::expr` should have a richer return type.
10611058
AssocConstValue::Impl(_) => repr != "_", // show if there is a meaningful value to show
10621059
AssocConstValue::None => unreachable!(),
10631060
} {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<section id="associatedconstant.X" class="associatedconstant"><a class="src rightside" href="../src/foo/anchors.rs.html#42">Source</a><h4 class="code-header">pub const <a href="#associatedconstant.X" class="constant">X</a>: <a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a> = 0i32</h4></section>
1+
<section id="associatedconstant.X" class="associatedconstant"><a class="src rightside" href="../src/foo/anchors.rs.html#42">Source</a><h4 class="code-header">pub const <a href="#associatedconstant.X" class="constant">X</a>: <a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a> = 0</h4></section>

tests/rustdoc-html/attributes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub enum Enum {
5959
pub trait Trait {
6060
//@ has 'foo/trait.Trait.html'
6161
//@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]/*[@class="code-attribute"]' '#[unsafe(link_section = "bar")]'
62-
//@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' 'const BAR: u32 = 0u32'
62+
//@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' 'const BAR: u32 = 0'
6363
#[unsafe(link_section = "bar")]
6464
const BAR: u32 = 0;
6565

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Ensure that we properly print the value `1` as `1` in the initializer of associated constants
2+
// that have user type "projection".
3+
//
4+
// We once used to evaluate the initializer in rustdoc and use rustc's MIR pretty-printer to
5+
// render the resulting MIR const value. This pretty printer matches on the type to interpret
6+
// the data and falls back to a cryptic `"{transmute(0x$data): $ty}"` for types it can't handle.
7+
// Crucially, when constructing the MIR const we passed the unnormalized type of the initializer,
8+
// i.e., the projection `<Struct as Trait>::Ty` instead of the normalized `u32` which the
9+
// pretty printer obviously can't handle.
10+
//
11+
// Now we no longer evaluate it and use a custom printer for the const expr.
12+
//
13+
// issue: <https://github.com/rust-lang/rust/issues/150312>
14+
15+
#![crate_name = "it"]
16+
17+
pub trait Trait {
18+
type Ty;
19+
20+
const CT: Self::Ty;
21+
}
22+
23+
pub struct Struct;
24+
25+
impl Trait for Struct {
26+
type Ty = u32;
27+
28+
//@ has it/struct.Struct.html
29+
//@ has - '//*[@id="associatedconstant.CT"]' 'const CT: Self::Ty = 1'
30+
const CT: Self::Ty = 1;
31+
}

tests/rustdoc-html/constant/assoc-consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
pub trait Foo {
22
//@ has assoc_consts/trait.Foo.html '//pre[@class="rust item-decl"]' \
3-
// 'const FOO: usize = 13usize;'
3+
// 'const FOO: usize = _;'
44
//@ has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize'
55
const FOO: usize = 12 + 1;
66
//@ has - '//*[@id="associatedconstant.FOO_NO_DEFAULT"]' 'const FOO_NO_DEFAULT: bool'

tests/rustdoc-html/deref/deref-to-primitive.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//@ has 'foo/struct.Foo.html'
44
//@ has - '//*[@id="deref-methods-i32"]' 'Methods from Deref<Target = i32>'
55
//@ has - '//*[@id="deref-methods-i32-1"]//*[@id="associatedconstant.BITS"]/h4' \
6-
// 'pub const BITS: u32 = 32u32'
6+
// 'pub const BITS: u32 = u32::BITS'
77
pub struct Foo(i32);
88

99
impl std::ops::Deref for Foo {

tests/rustdoc-html/display-hidden-items.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub trait TraitHidden {}
2020
//@ has 'foo/index.html' '//dt/a[@class="trait"]' 'Trait'
2121
pub trait Trait {
2222
//@ has 'foo/trait.Trait.html'
23-
//@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' '#[doc(hidden)] const BAR: u32 = 0u32'
23+
//@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' '#[doc(hidden)] const BAR: u32 = 0'
2424
#[doc(hidden)]
2525
const BAR: u32 = 0;
2626

@@ -44,7 +44,7 @@ impl Struct {
4444
}
4545

4646
impl Trait for Struct {
47-
//@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' '#[doc(hidden)] const BAR: u32 = 0u32'
47+
//@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' '#[doc(hidden)] const BAR: u32 = 0'
4848
//@ has - '//*[@id="method.foo"]/*[@class="code-header"]' '#[doc(hidden)] fn foo()'
4949
}
5050
//@ has - '//*[@id="impl-TraitHidden-for-Struct"]/*[@class="code-header"]' 'impl TraitHidden for Struct'

tests/rustdoc-html/impl/impl-associated-items-order.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ impl Bar {
1616
// 'pub fn foo()'
1717
pub fn foo() {}
1818
//@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[1]/h4' \
19-
// 'pub const X: u8 = 12u8'
19+
// 'pub const X: u8 = 12'
2020
pub const X: u8 = 12;
2121
//@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[2]/h4' \
2222
// 'pub type Y = u8'
@@ -34,7 +34,7 @@ impl Foo for Bar {
3434
// 'type Z = u8'
3535
type Z = u8;
3636
//@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[1]/h4' \
37-
// 'const W: u32 = 12u32'
37+
// 'const W: u32 = 12'
3838
const W: u32 = 12;
3939
//@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[3]/h4' \
4040
// 'fn yeay()'
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Ensure that we don't unconditionally evaluate the initializer of associated constants.
2+
//
3+
// We once used to evaluate them so we could display more kinds of expressions
4+
// (like `1 + 1` as `2`) given the fact that we generally only want to render
5+
// literals (otherwise we would risk dumping extremely large exprs or leaking
6+
// private struct fields).
7+
//
8+
// However, that deviated from rustc's behavior, made rustdoc accept less code
9+
// and was understandably surprising to users. So let's not.
10+
//
11+
// In the future we *might* provide users a mechanism to control this behavior.
12+
// E.g., via a new `#[doc(...)]` attribute.
13+
//
14+
// See also:
15+
// issue: <https://github.com/rust-lang/rust/issues/131625>
16+
// issue: <https://github.com/rust-lang/rust/issues/149635>
17+
18+
//@ check-pass
19+
20+
pub struct Type;
21+
22+
impl Type {
23+
pub const K0: () = panic!();
24+
pub const K1: std::convert::Infallible = loop {};
25+
}
26+
27+
pub trait Trait {
28+
const K2: i32 = panic!();
29+
}
30+
31+
impl Trait for Type {
32+
const K2: i32 = loop {};
33+
}

0 commit comments

Comments
 (0)