rust icon indicating copy to clipboard operation
rust copied to clipboard

`const` blocks as a `mod` item

Open GrigorenkoPV opened this issue 1 month ago • 25 comments

Tracking issue: rust-lang/rust#149226

This adds support for writing const { ... } as an item in a module. In the current implementation, this is a unique AST item that gets lowered to const _: () = const { ... }; in HIR.

rustfmt support included.

TODO:

  • pub const { ... } does not make sense (see rust-lang/rust#147136). Reject it. Should this be rejected by the parser or smth?
  • Improve diagnostics (preferably they should not mention the fake _ ident).
  • There's an invariant ConstBlockItem{body: Expr{kind: ConstBlock(..), ..}}. Get rid of it?

GrigorenkoPV avatar Nov 21 '25 12:11 GrigorenkoPV

The job tidy failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)

error: expected item, found keyword `const`
##[error]  --> /checkout/library/core/src/ptr/alignment.rs:18:1
   |
18 | const { assert!(size_of::<Alignment>() == size_of::<usize>()) }
   | ^^^^^ expected item
   |
   = note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>

error: expected item, found keyword `const`
---

error: expected item, found keyword `const`
##[error]   --> /checkout/library/coretests/tests/cmp.rs:241:5
    |
241 |     const { assert!(S(1) == S(1)) }
    |     ^^^^^ expected item
    |
    = note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>

Bootstrap failed while executing `test src/tools/tidy tidyselftest --extra-checks=py,cpp,js,spellcheck`

rust-log-analyzer avatar Nov 21 '25 12:11 rust-log-analyzer

The job tidy failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
fmt: checked 6559 files
tidy check
tidy [rustdoc_json (src)]: `rustdoc-json-types` modified, checking format version
tidy: Skipping binary file check, read-only filesystem
tidy [features]: /checkout/compiler/rustc_feature/src/unstable.rs:449: no tracking issue for feature const_block_items
tidy [features]: FAIL
removing old virtual environment
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'venv'
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'virtualenv'
Requirement already satisfied: pip in ./build/venv/lib/python3.10/site-packages (25.3)
linting python files
---
linting javascript files and applying suggestions
Running eslint on rustdoc JS files
info: ES-Check: there were no ES version matching errors!  🎉
typechecking javascript files
tidy: The following check failed: features
Command `/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools-bin/rust-tidy /checkout /checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo /checkout/obj/build 4 /node/bin/yarn --extra-checks=py,cpp,js,spellcheck` failed with exit code 1
Created at: src/bootstrap/src/core/build_steps/tool.rs:1594:23
Executed at: src/bootstrap/src/core/build_steps/test.rs:1285:29

Command has failed. Rerun with -v to see more details.
Bootstrap failed while executing `test src/tools/tidy tidyselftest --extra-checks=py,cpp,js,spellcheck`
Build completed unsuccessfully in 0:02:57
  local time: Fri Nov 21 20:33:59 UTC 2025
  network time: Fri, 21 Nov 2025 20:33:59 GMT
##[error]Process completed with exit code 1.

rust-log-analyzer avatar Nov 21 '25 20:11 rust-log-analyzer

The job pr-check-2 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)

rust-log-analyzer avatar Nov 22 '25 21:11 rust-log-analyzer

The job pr-check-2 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
121 |     pub fn parse_item(
    |            ^^^^^^^^^^
help: provide the argument
    |
 64 |             let item = match parser.parse_item(ForceCollect::No, /* AllowConstBlockItems */) {
    |                                                                ++++++++++++++++++++++++++++

error[E0061]: this method takes 2 arguments but 1 argument was supplied
   --> src/tools/rustfmt/src/parse/macros/mod.rs:70:42
    |
 70 |         |parser: &mut Parser<'b>| parser.parse_item(ForceCollect::No),
    |                                          ^^^^^^^^^^------------------ argument #2 of type `AllowConstBlockItems` is missing
    |
note: method defined here
   --> /checkout/compiler/rustc_parse/src/parser/item.rs:121:12
    |
121 |     pub fn parse_item(
    |            ^^^^^^^^^^
help: provide the argument
    |
 70 |         |parser: &mut Parser<'b>| parser.parse_item(ForceCollect::No, /* AllowConstBlockItems */),
    |                                                                     ++++++++++++++++++++++++++++

error[E0004]: non-exhaustive patterns: `ItemKind::ConstBlock(_)` not covered
    --> src/tools/rustfmt/src/visitor.rs:488:19
     |
 488 |             match item.kind {
     |                   ^^^^^^^^^ pattern `ItemKind::ConstBlock(_)` not covered
     |

rust-log-analyzer avatar Nov 25 '25 21:11 rust-log-analyzer

The job aarch64-gnu-llvm-20-2 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
 124 |         allow_const_block_items: AllowConstBlockItems,
     |         ---------------------------------------------
help: provide the argument
     |
2242 |         .parse_item(ForceCollect::No, /* AllowConstBlockItems */)
     |                                     ++++++++++++++++++++++++++++

error[E0061]: this method takes 2 arguments but 1 argument was supplied
    --> compiler/rustc_parse/src/parser/tests.rs:2257:59
     |
2257 |     with_error_checking_parse(source_str, &psess(), |p| p.parse_item(ForceCollect::No))
     |                                                           ^^^^^^^^^^------------------ argument #2 of type `AllowConstBlockItems` is missing
     |
note: method defined here
    --> compiler/rustc_parse/src/parser/item.rs:121:12
     |
 121 |     pub fn parse_item(
     |            ^^^^^^^^^^
...
 124 |         allow_const_block_items: AllowConstBlockItems,
     |         ---------------------------------------------
help: provide the argument
     |
2257 |     with_error_checking_parse(source_str, &psess(), |p| p.parse_item(ForceCollect::No, /* AllowConstBlockItems */))
     |                                                                                      ++++++++++++++++++++++++++++

[RUSTC-TIMING] rustc_mir_dataflow test:true 5.559
   Compiling rustc_ty_utils v0.0.0 (/checkout/compiler/rustc_ty_utils)
For more information about this error, try `rustc --explain E0061`.

rust-log-analyzer avatar Nov 26 '25 19:11 rust-log-analyzer

Some changes occurred in src/tools/rustfmt

cc @rust-lang/rustfmt

rustbot avatar Nov 29 '25 21:11 rustbot

r? @jdonszelmann

rustbot has assigned @jdonszelmann. They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

rustbot avatar Nov 29 '25 21:11 rustbot

I can review this from compiler. @rust-lang/lang do you want to sign off on this in any way, formally starting a lang experiment for example?

jdonszelmann avatar Dec 01 '25 12:12 jdonszelmann

@rustbot author

jdonszelmann avatar Dec 01 '25 12:12 jdonszelmann

Reminder, once the PR becomes ready for a review, use @rustbot ready.

rustbot avatar Dec 01 '25 12:12 rustbot

I can review this from compiler. @rust-lang/lang do you want to sign off on this in any way, formally starting a lang experiment for example?

I see that, @GrigorenkoPV, you created a tracking issue for the experiment. Thanks for doing that. We need a lang champion for the experiment; I'll nominate this so we can discuss and assign one.

traviscross avatar Dec 01 '25 14:12 traviscross

Hmm, I worry that this would muddy the "items are items" thing, because now typing the same thing will work differently in different places, which seems non-great.

I wonder about maybe doing this a different way, like how we allow omitting -> () on functions, so maybe we could instead allow const _ = …; that has to be unit-typed? That way it'd clearly be an item even in a place where inline const expressions are also valid.

scottmcm avatar Dec 03 '25 18:12 scottmcm

We discussed this in today's @rust-lang/lang meeting.

We're happy to see a lang experiment for this.

I would be happy to serve as the champion. @GrigorenkoPV, please check in with me as the experiment progresses, so we can keep lang up to date with the results of the experiment.

joshtriplett avatar Dec 03 '25 18:12 joshtriplett

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

rustbot avatar Dec 04 '25 16:12 rustbot

:umbrella: The latest upstream changes (presumably #149646) made this pull request unmergeable. Please resolve the merge conflicts.

bors avatar Dec 05 '25 02:12 bors

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

rustbot avatar Dec 05 '25 22:12 rustbot

Hmm, I worry that this would muddy the "items are items" thing, because now typing the same thing will work differently in different places, which seems non-great.

True.

I wonder about maybe doing this a different way, like how we allow omitting -> () on functions, so maybe we could instead allow const _ = …; that has to be unit-typed? That way it'd clearly be an item even in a place where inline const expressions are also valid.

That sounds like a good idea. I will probably try to implement this as well (but later), as an alternative to this approach or maybe as a generally nice-to-have feature.

I guess further discussion with lang would be needed here, but I'd prefer to have it after I at least have some sort of a prototype.


@rustbot ready

Out of the remaining issues (listed in OP):

I would prefer to deal with diagnostic improvements later, outside of this PR, if that's acceptable. This includes exorcising _ identifiers from, general tailoring of the messages, and rejecting visibility qualifiers, which have no effect for const block items.

As for the AllowConstBlockItems::FIXME, I'm fine with either fixing them later (and meanwhile just adding a note about what they actually mean), or blocking this PR until they are gotten rid of, which would mean I would probably have to ping some people, more knowledgeable about the involved parts of the compiler, or maybe pester them on Zulip or smth.

GrigorenkoPV avatar Dec 05 '25 22:12 GrigorenkoPV

left a comment at places where we use FIXME still (I thope all?) with my thoughts. If you agree, let's change to that. Diagnostics changes are ok, maybe make a not about that on the tracking issue so we don't forget. Other than that pretty much good from me and lang also it seems. Great!

@rustbot author

jdonszelmann avatar Dec 06 '25 16:12 jdonszelmann

about the refactoring of that invariant, also maybe make a note of that on the tracking issue. lgtm otherwise

jdonszelmann avatar Dec 06 '25 16:12 jdonszelmann

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

rustbot avatar Dec 06 '25 19:12 rustbot

Got rid of FIXME, rebased, updated the tracking issue.

@rustbot ready

GrigorenkoPV avatar Dec 06 '25 19:12 GrigorenkoPV

https://github.com/rust-lang/rust/pull/149174#discussion_r2595414977 @rustbot author

jdonszelmann avatar Dec 06 '25 20:12 jdonszelmann

Argh, pushed an outdated version from a wrong machine. I guess even NixOS can't always help when managing multiple devices.

@rustbot ready Hopefully for real this time

GrigorenkoPV avatar Dec 06 '25 20:12 GrigorenkoPV

The job aarch64-gnu-llvm-20-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
   Compiling rustc_expand v0.0.0 (/checkout/compiler/rustc_expand)
error[E0277]: the trait bound `AllowConstBlockItems: From<bool>` is not satisfied
   --> compiler/rustc_expand/src/proc_macro.rs:159:66
    |
159 |             match parser.parse_item(ForceCollect::No, (!is_stmt).into()) {
    |                                                                  ^^^^ the trait `From<bool>` is not implemented for `AllowConstBlockItems`
    |
    = note: required for `bool` to implement `Into<AllowConstBlockItems>`

For more information about this error, try `rustc --explain E0277`.
[RUSTC-TIMING] rustc_expand test:false 0.932
error: could not compile `rustc_expand` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

rust-log-analyzer avatar Dec 06 '25 20:12 rust-log-analyzer

Nope :/

jdonszelmann avatar Dec 06 '25 20:12 jdonszelmann

by the way, why does a global const block desugar to const _: () = const {...}? Is that any different than const _: () = { ... }?

jdonszelmann avatar Dec 07 '25 21:12 jdonszelmann

by the way, why does a global const block desugar to const _: () = const {...}?

Ease of implementation, really.

Is that any different than const _: () = { ... }?

To the best of my knowledge, it shouldn't matter.

GrigorenkoPV avatar Dec 08 '25 12:12 GrigorenkoPV

then I think it might be better not to.

jdonszelmann avatar Dec 08 '25 14:12 jdonszelmann

the const block will get its own defid, so with it we effectively allocate two

jdonszelmann avatar Dec 08 '25 14:12 jdonszelmann

@rustbot author

jdonszelmann avatar Dec 09 '25 05:12 jdonszelmann