diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index c435e632815a..591abdaa2683 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -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, + pub id: NodeId, + pub span: Span, + pub block: Box, } impl ConstBlockItem { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 906e5ca8a800..b497c6beeb98 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -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) }), ), diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 8ee084628599..68054b06e39f 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -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, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index a9526ce78a50..6b61504f2327 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -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`. /// diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 461d27694dbe..7a7261cf7b95 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -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 { diff --git a/tests/ui/consts/const-block-items/assert-fail.stderr b/tests/ui/consts/const-block-items/assert-fail.stderr index 78bd89478541..b1444dc5e0d0 100644 --- a/tests/ui/consts/const-block-items/assert-fail.stderr +++ b/tests/ui/consts/const-block-items/assert-fail.stderr @@ -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 diff --git a/tests/ui/consts/const-block-items/hir.rs b/tests/ui/consts/const-block-items/hir.rs new file mode 100644 index 000000000000..1d9c5e91b57e --- /dev/null +++ b/tests/ui/consts/const-block-items/hir.rs @@ -0,0 +1,10 @@ +//@ build-pass +//@ compile-flags: -Zunpretty=hir + +#![feature(const_block_items)] + +const { + // foo +} + +fn main() { } diff --git a/tests/ui/consts/const-block-items/hir.stdout b/tests/ui/consts/const-block-items/hir.stdout new file mode 100644 index 000000000000..e2df04e98d4e --- /dev/null +++ b/tests/ui/consts/const-block-items/hir.stdout @@ -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() { } diff --git a/tests/ui/parser/const-block-items/inner-attr.rs b/tests/ui/parser/const-block-items/inner-attr.rs new file mode 100644 index 000000000000..9ab945259160 --- /dev/null +++ b/tests/ui/parser/const-block-items/inner-attr.rs @@ -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() {} diff --git a/tests/ui/parser/const-block-items/inner-attr.stderr b/tests/ui/parser/const-block-items/inner-attr.stderr new file mode 100644 index 000000000000..74ac902e5961 --- /dev/null +++ b/tests/ui/parser/const-block-items/inner-attr.stderr @@ -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 + diff --git a/tests/ui/parser/const-block-items/pub.rs b/tests/ui/parser/const-block-items/pub.rs new file mode 100644 index 000000000000..b76d30d9bda1 --- /dev/null +++ b/tests/ui/parser/const-block-items/pub.rs @@ -0,0 +1,10 @@ +#![feature(const_block_items)] + +//@ check-pass + +// FIXME(const_block_items): `pub`` is useless here +pub const { + assert!(true); +} + +fn main() { } diff --git a/tests/ui/parser/const-block-items/unsafe.rs b/tests/ui/parser/const-block-items/unsafe.rs new file mode 100644 index 000000000000..f53dfab7a0a2 --- /dev/null +++ b/tests/ui/parser/const-block-items/unsafe.rs @@ -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() { } diff --git a/tests/ui/parser/const-block-items/unsafe.stderr b/tests/ui/parser/const-block-items/unsafe.stderr new file mode 100644 index 000000000000..0d38af838b3e --- /dev/null +++ b/tests/ui/parser/const-block-items/unsafe.stderr @@ -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 +