const_block_items: do not create an AnonConst

This commit is contained in:
Pavel Grigorenko 2025-12-10 22:33:14 +03:00
parent e77b11924f
commit a315d230d5
13 changed files with 125 additions and 40 deletions

View file

@ -3898,8 +3898,9 @@ impl ConstItemRhs {
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct ConstBlockItem {
// FIXME(const_block_items): current invariant is body.kind == InlineConst
pub body: Box<Expr>,
pub id: NodeId,
pub span: Span,
pub block: Box<Block>,
}
impl ConstBlockItem {

View file

@ -308,12 +308,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_define_opaque(hir_id, &define_opaque);
hir::ItemKind::Const(ident, generics, ty, rhs)
}
ItemKind::ConstBlock(ConstBlockItem { body }) => hir::ItemKind::Const(
ItemKind::ConstBlock(ConstBlockItem { span, id, block }) => hir::ItemKind::Const(
self.lower_ident(ConstBlockItem::IDENT),
hir::Generics::empty(),
self.arena.alloc(self.ty_tup(DUMMY_SP, &[])),
hir::ConstItemRhs::Body({
let body = self.lower_expr_mut(body);
let body = hir::Expr {
hir_id: self.lower_node_id(*id),
kind: hir::ExprKind::Block(self.lower_block(block, false), None),
span: self.lower_span(*span),
};
self.record_body(&[], body)
}),
),

View file

@ -205,8 +205,16 @@ impl<'a> State<'a> {
define_opaque.as_deref(),
);
}
ast::ItemKind::ConstBlock(ast::ConstBlockItem { body }) => {
self.print_expr(body, FixupContext::default())
ast::ItemKind::ConstBlock(ast::ConstBlockItem { id: _, span: _, block }) => {
let ib = self.ibox(INDENT_UNIT);
self.word("const");
self.nbsp();
{
let cb = self.cbox(0);
let ib = self.ibox(0);
self.print_block_with_attrs(block, &[], cb, ib);
}
self.end(ib);
}
ast::ItemKind::Const(box ast::ConstItem {
defaultness,

View file

@ -275,15 +275,13 @@ impl<'a> Parser<'a> {
self.parse_item_impl(attrs, def_(), false)?
} else if let AllowConstBlockItems::Yes | AllowConstBlockItems::DoesNotMatter =
allow_const_block_items
&& self.token.is_keyword(kw::Const)
&& self.look_ahead(1, |t| *t == token::OpenBrace || t.is_metavar_block())
&& self.check_inline_const(0)
{
// CONST BLOCK ITEM
self.psess.gated_spans.gate(sym::const_block_items, self.token.span);
if let AllowConstBlockItems::DoesNotMatter = allow_const_block_items {
debug!("Parsing a const block item that does not matter: {:?}", self.token.span);
};
ItemKind::ConstBlock(ConstBlockItem { body: self.parse_expr()? })
ItemKind::ConstBlock(self.parse_const_block_item()?)
} else if let Const::Yes(const_span) = self.parse_constness(case) {
// CONST ITEM
self.recover_const_mut(const_span);
@ -1473,6 +1471,14 @@ impl<'a> Parser<'a> {
}
}
fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {
self.expect_keyword(exp!(Const))?;
let const_span = self.prev_token.span;
self.psess.gated_spans.gate(sym::const_block_items, const_span);
let block = self.parse_block()?;
Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })
}
/// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in
/// `mutability`.
///

View file

@ -2898,23 +2898,27 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
);
self.resolve_define_opaques(define_opaque);
}
ItemKind::ConstBlock(ConstBlockItem { body }) => self.with_generic_param_rib(
&[],
RibKind::Item(HasGenericParams::No, def_kind),
item.id,
LifetimeBinderKind::ConstItem,
DUMMY_SP,
|this| {
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
this.with_constant_rib(
IsRepeatExpr::No,
ConstantHasGenerics::Yes,
Some((ConstBlockItem::IDENT, ConstantItemKind::Const)),
|this| this.visit_expr(body),
ItemKind::ConstBlock(ConstBlockItem { id: _, span: _, block }) => self
.with_generic_param_rib(
&[],
RibKind::Item(HasGenericParams::No, def_kind),
item.id,
LifetimeBinderKind::ConstItem,
DUMMY_SP,
|this| {
this.with_lifetime_rib(
LifetimeRibKind::Elided(LifetimeRes::Infer),
|this| {
this.with_constant_rib(
IsRepeatExpr::No,
ConstantHasGenerics::Yes,
Some((ConstBlockItem::IDENT, ConstantItemKind::Const)),
|this| this.resolve_labeled_block(None, block.id, block),
)
},
);
})
},
),
},
),
ItemKind::Use(use_tree) => {
let maybe_exported = match use_tree.kind {

View file

@ -2,25 +2,13 @@ error[E0080]: evaluation panicked: assertion failed: false
--> $DIR/assert-fail.rs:5:9
|
LL | const { assert!(false) }
| ^^^^^^^^^^^^^^ evaluation of `_::{constant#0}` failed here
note: erroneous constant encountered
--> $DIR/assert-fail.rs:5:1
|
LL | const { assert!(false) }
| ^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ evaluation of `_` failed here
error[E0080]: evaluation panicked: assertion failed: 2 + 2 == 5
--> $DIR/assert-fail.rs:7:9
|
LL | const { assert!(2 + 2 == 5) }
| ^^^^^^^^^^^^^^^^^^^ evaluation of `_::{constant#0}` failed here
note: erroneous constant encountered
--> $DIR/assert-fail.rs:7:1
|
LL | const { assert!(2 + 2 == 5) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here
error: aborting due to 2 previous errors

View file

@ -0,0 +1,10 @@
//@ build-pass
//@ compile-flags: -Zunpretty=hir
#![feature(const_block_items)]
const {
// foo
}
fn main() { }

View file

@ -0,0 +1,14 @@
//@ build-pass
//@ compile-flags: -Zunpretty=hir
#![feature(const_block_items)]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;
const _: () =
{
// foo
};
fn main() { }

View file

@ -0,0 +1,9 @@
#![feature(const_block_items)]
const {
#![expect(unused)] //~ ERROR: an inner attribute is not permitted in this context
let a = 1;
assert!(true);
}
fn main() {}

View file

@ -0,0 +1,13 @@
error: an inner attribute is not permitted in this context
--> $DIR/inner-attr.rs:4:5
|
LL | #![expect(unused)]
| ^^^^^^^^^^^^^^^^^^
...
LL | fn main() {}
| ------------ the inner attribute doesn't annotate this function
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
error: aborting due to 1 previous error

View file

@ -0,0 +1,10 @@
#![feature(const_block_items)]
//@ check-pass
// FIXME(const_block_items): `pub`` is useless here
pub const {
assert!(true);
}
fn main() { }

View file

@ -0,0 +1,10 @@
#![feature(const_block_items)]
const unsafe fn foo() -> bool {
true
}
const unsafe { assert!(foo()) }
//~^ ERROR: expected one of `extern` or `fn`, found `{`
fn main() { }

View file

@ -0,0 +1,8 @@
error: expected one of `extern` or `fn`, found `{`
--> $DIR/unsafe.rs:7:14
|
LL | const unsafe { assert!(foo()) }
| ^ expected one of `extern` or `fn`
error: aborting due to 1 previous error