rust-lang / rust-lang/rust

Modify rendering of `const` params in types to make it clear they are const params and not type params

Open
#151,792 4 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-const-generics A-diagnostics D-diagnostic-infra T-compiler T-types
Dominant language
Rust
Stars
119k
Forks
16.2k
PR merge metrics
PR metrics pending

Description

Currently const parameters are displayed with either the computed value of a valtree, or the name of the const parameter on its own. This means that single letter type parameters, consts used as the const value and single letter const names can't be differentiated when looking at type path in diagnostics.

I propose that we differentiate between these by increasing the verbosity of const parameters in their rendering.

  • ty::ConstKind::Param(_): Type<const N: usize> instead of Type<N>
  • ty::ConstKind::Value(_): Type<const N: usize = 42> or at least Type<const { 42 }> instead of Type<42>

Currently ty::ConstKind::Param only has the name of the type param, while ty::ConstKind::Value doesn't have any awareness of it being a const param and having a name, but it knows its value and type. There are other ty::ConstKind variants that should also be evaluated for different rendering.

It is likely that we should also render const items with their name when possible. We might want to specialize the output of array lengths, which today are given the "fake" name N and instead use a description rather than that ("expected [_; const { 0 }], found [_; const N]" or in other cases[_; { array length }]).

Because const params are not used as often as type parameters, the increase in verbosity shouldn't have as much of an impact on the output as there would be if we changed those.

I noticed while working on yet another derived builder using const params to track fields being set/unset, that the output for const params wasn't great:

error[E0599]: no method named `build` found for struct `PartialTest<false, true>` in the current scope
  --> tests/no_compile/missing_fields_in_builder.rs:13:33
   |
 3 | #[bitfield(u32, default = 0, forbid_overlaps)]
   | ---------------------------------------------- method `build` not found for this struct
...
13 |     Test::builder().with_bar(1).build();
   |                                 ^^^^^ method not found in `PartialTest<false, true>`
   |
   = note: the method was found for
           - `PartialTest<true, true>`

error[E0599]: no method named `with_bar` found for struct `PartialTest<true, true>` in the current scope
  --> tests/no_compile/missing_fields_in_builder.rs:15:45
   |
 3 | #[bitfield(u32, default = 0, forbid_overlaps)]
   | ---------------------------------------------- method `with_bar` not found for this struct
...
15 |     Test::builder().with_bar(1).with_foo(1).with_bar(2).build();
   |                                             ^^^^^^^^ method not found in `PartialTest<true, true>`
   |
   = note: the method was found for
           - `PartialTest<foo, false>`
help: one of the expressions' fields has a method of the same name
   |
15 |     Test::builder().with_bar(1).with_foo(1).value.with_bar(2).build();
   |                                             ++++++

In the first case, PartialTest<true, true> doesn't make it clear that every const param should have been enabled, while PartialTest<const foo: bool = true, const bar: bool = true> would communicate that information better. In the second case, PartialTest<foo, true>, the use of a non-standard case for the const param's name makes it easier to misread, while PartialTest<const foo: bool, const bar: bool = true> makes the distinction of a set or unset const param absolutely clear.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing how ty::ConstKind variants are rendered in type paths and diagnostics, using the examples in the issue as expected distinctions. Evaluate parameter, value, const-item, and array-length cases, then confirm that diagnostics clearly distinguish const parameters from type parameters and show useful names or values.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.