Skip to content

Commit 0bb1545

Browse files
authored
Rollup merge of rust-lang#149174 - GrigorenkoPV:const_block_item, r=me,ytmimi
`const` blocks as a `mod` item Tracking issue: rust-lang#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#147136). Reject it. Should this be rejected by the parser or smth? - Improve diagnostics (preferably they should not mention the fake `_` ident).
2 parents a18e6d9 + d144915 commit 0bb1545

54 files changed

Lines changed: 551 additions & 85 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_ast/src/ast.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3626,6 +3626,7 @@ impl Item {
36263626
pub fn opt_generics(&self) -> Option<&Generics> {
36273627
match &self.kind {
36283628
ItemKind::ExternCrate(..)
3629+
| ItemKind::ConstBlock(_)
36293630
| ItemKind::Use(_)
36303631
| ItemKind::Mod(..)
36313632
| ItemKind::ForeignMod(_)
@@ -3895,6 +3896,17 @@ impl ConstItemRhs {
38953896
}
38963897
}
38973898

3899+
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
3900+
pub struct ConstBlockItem {
3901+
pub id: NodeId,
3902+
pub span: Span,
3903+
pub block: Box<Block>,
3904+
}
3905+
3906+
impl ConstBlockItem {
3907+
pub const IDENT: Ident = Ident { name: kw::Underscore, span: DUMMY_SP };
3908+
}
3909+
38983910
// Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
38993911
#[derive(Clone, Encodable, Decodable, Debug)]
39003912
pub enum ItemKind {
@@ -3914,6 +3926,11 @@ pub enum ItemKind {
39143926
///
39153927
/// E.g., `const FOO: i32 = 42;`.
39163928
Const(Box<ConstItem>),
3929+
/// A module-level const block.
3930+
/// Equivalent to `const _: () = const { ... };`.
3931+
///
3932+
/// E.g., `const { assert!(true) }`.
3933+
ConstBlock(ConstBlockItem),
39173934
/// A function declaration (`fn`).
39183935
///
39193936
/// E.g., `fn foo(bar: usize) -> usize { .. }`.
@@ -3990,6 +4007,8 @@ impl ItemKind {
39904007
| ItemKind::MacroDef(ident, _)
39914008
| ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),
39924009

4010+
ItemKind::ConstBlock(_) => Some(ConstBlockItem::IDENT),
4011+
39934012
ItemKind::Use(_)
39944013
| ItemKind::ForeignMod(_)
39954014
| ItemKind::GlobalAsm(_)
@@ -4003,9 +4022,9 @@ impl ItemKind {
40034022
pub fn article(&self) -> &'static str {
40044023
use ItemKind::*;
40054024
match self {
4006-
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
4007-
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
4008-
| Delegation(..) | DelegationMac(..) => "a",
4025+
Use(..) | Static(..) | Const(..) | ConstBlock(..) | Fn(..) | Mod(..)
4026+
| GlobalAsm(..) | TyAlias(..) | Struct(..) | Union(..) | Trait(..) | TraitAlias(..)
4027+
| MacroDef(..) | Delegation(..) | DelegationMac(..) => "a",
40094028
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
40104029
}
40114030
}
@@ -4016,6 +4035,7 @@ impl ItemKind {
40164035
ItemKind::Use(..) => "`use` import",
40174036
ItemKind::Static(..) => "static item",
40184037
ItemKind::Const(..) => "constant item",
4038+
ItemKind::ConstBlock(..) => "const block",
40194039
ItemKind::Fn(..) => "function",
40204040
ItemKind::Mod(..) => "module",
40214041
ItemKind::ForeignMod(..) => "extern block",
@@ -4045,7 +4065,18 @@ impl ItemKind {
40454065
| Self::Trait(box Trait { generics, .. })
40464066
| Self::TraitAlias(box TraitAlias { generics, .. })
40474067
| Self::Impl(Impl { generics, .. }) => Some(generics),
4048-
_ => None,
4068+
4069+
Self::ExternCrate(..)
4070+
| Self::Use(..)
4071+
| Self::Static(..)
4072+
| Self::ConstBlock(..)
4073+
| Self::Mod(..)
4074+
| Self::ForeignMod(..)
4075+
| Self::GlobalAsm(..)
4076+
| Self::MacCall(..)
4077+
| Self::MacroDef(..)
4078+
| Self::Delegation(..)
4079+
| Self::DelegationMac(..) => None,
40494080
}
40504081
}
40514082
}

compiler/rustc_ast/src/visit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ macro_rules! common_visitor_and_walkers {
425425
ByRef,
426426
Closure,
427427
Const,
428+
ConstBlockItem,
428429
ConstItem,
429430
ConstItemRhs,
430431
Defaultness,
@@ -825,6 +826,8 @@ macro_rules! common_visitor_and_walkers {
825826
visit_visitable!($($mut)? vis, use_tree),
826827
ItemKind::Static(item) =>
827828
visit_visitable!($($mut)? vis, item),
829+
ItemKind::ConstBlock(item) =>
830+
visit_visitable!($($mut)? vis, item),
828831
ItemKind::Const(item) =>
829832
visit_visitable!($($mut)? vis, item),
830833
ItemKind::Mod(safety, ident, mod_kind) =>

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
205205
| ItemKind::Use(..)
206206
| ItemKind::Static(..)
207207
| ItemKind::Const(..)
208+
| ItemKind::ConstBlock(..)
208209
| ItemKind::Mod(..)
209210
| ItemKind::ForeignMod(..)
210211
| ItemKind::GlobalAsm(..)
@@ -282,8 +283,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
282283
self.lower_define_opaque(hir_id, define_opaque);
283284
hir::ItemKind::Static(*m, ident, ty, body_id)
284285
}
285-
ItemKind::Const(box ast::ConstItem {
286-
ident, generics, ty, rhs, define_opaque, ..
286+
ItemKind::Const(box ConstItem {
287+
defaultness: _,
288+
ident,
289+
generics,
290+
ty,
291+
rhs,
292+
define_opaque,
287293
}) => {
288294
let ident = self.lower_ident(*ident);
289295
let (generics, (ty, rhs)) = self.lower_generics(
@@ -302,6 +308,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
302308
self.lower_define_opaque(hir_id, &define_opaque);
303309
hir::ItemKind::Const(ident, generics, ty, rhs)
304310
}
311+
ItemKind::ConstBlock(ConstBlockItem { span, id, block }) => hir::ItemKind::Const(
312+
self.lower_ident(ConstBlockItem::IDENT),
313+
hir::Generics::empty(),
314+
self.arena.alloc(self.ty_tup(DUMMY_SP, &[])),
315+
hir::ConstItemRhs::Body({
316+
let body = hir::Expr {
317+
hir_id: self.lower_node_id(*id),
318+
kind: hir::ExprKind::Block(self.lower_block(block, false), None),
319+
span: self.lower_span(*span),
320+
};
321+
self.record_body(&[], body)
322+
}),
323+
),
305324
ItemKind::Fn(box Fn {
306325
sig: FnSig { decl, header, span: fn_sig_span },
307326
ident,

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
537537
gate_all!(super_let, "`super let` is experimental");
538538
gate_all!(frontmatter, "frontmatters are experimental");
539539
gate_all!(coroutines, "coroutine syntax is experimental");
540+
gate_all!(const_block_items, "const block items are experimental");
540541

541542
if !visitor.features.never_patterns() {
542543
if let Some(spans) = spans.get(&sym::never_patterns) {

compiler/rustc_ast_pretty/src/pprust/state/item.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,17 @@ impl<'a> State<'a> {
205205
define_opaque.as_deref(),
206206
);
207207
}
208+
ast::ItemKind::ConstBlock(ast::ConstBlockItem { id: _, span: _, block }) => {
209+
let ib = self.ibox(INDENT_UNIT);
210+
self.word("const");
211+
self.nbsp();
212+
{
213+
let cb = self.cbox(0);
214+
let ib = self.ibox(0);
215+
self.print_block_with_attrs(block, &[], cb, ib);
216+
}
217+
self.end(ib);
218+
}
208219
ast::ItemKind::Const(box ast::ConstItem {
209220
defaultness,
210221
ident,

compiler/rustc_builtin_macros/src/cfg_eval.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_expand::base::{Annotatable, ExtCtxt};
99
use rustc_expand::config::StripUnconfigured;
1010
use rustc_expand::configure;
1111
use rustc_feature::Features;
12-
use rustc_parse::parser::{ForceCollect, Parser};
12+
use rustc_parse::parser::{AllowConstBlockItems, ForceCollect, Parser};
1313
use rustc_session::Session;
1414
use rustc_span::{Span, sym};
1515
use smallvec::SmallVec;
@@ -110,7 +110,8 @@ impl CfgEval<'_> {
110110
let res: PResult<'_, Annotatable> = try {
111111
match annotatable {
112112
Annotatable::Item(_) => {
113-
let item = parser.parse_item(ForceCollect::Yes)?.unwrap();
113+
let item =
114+
parser.parse_item(ForceCollect::Yes, AllowConstBlockItems::Yes)?.unwrap();
114115
Annotatable::Item(self.flat_map_item(item).pop().unwrap())
115116
}
116117
Annotatable::AssocItem(_, ctxt) => {

compiler/rustc_builtin_macros/src/source_util.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_expand::base::{
1313
};
1414
use rustc_expand::module::DirOwnership;
1515
use rustc_parse::lexer::StripTokens;
16-
use rustc_parse::parser::ForceCollect;
16+
use rustc_parse::parser::{AllowConstBlockItems, ForceCollect};
1717
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error};
1818
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
1919
use rustc_session::parse::ParseSess;
@@ -168,7 +168,7 @@ pub(crate) fn expand_include<'cx>(
168168
));
169169
let mut ret = SmallVec::new();
170170
loop {
171-
match p.parse_item(ForceCollect::No) {
171+
match p.parse_item(ForceCollect::No, AllowConstBlockItems::Yes) {
172172
Err(err) => {
173173
err.emit();
174174
break;

compiler/rustc_expand/src/base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_hir::limit::Limit;
2222
use rustc_hir::{Stability, find_attr};
2323
use rustc_lint_defs::RegisteredTools;
2424
use rustc_parse::MACRO_ARGUMENTS;
25-
use rustc_parse::parser::{ForceCollect, Parser};
25+
use rustc_parse::parser::{AllowConstBlockItems, ForceCollect, Parser};
2626
use rustc_session::Session;
2727
use rustc_session::parse::ParseSess;
2828
use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
@@ -1472,7 +1472,7 @@ pub(crate) fn stream_pretty_printing_compatibility_hack(
14721472
let mut parser = Parser::new(psess, stream.clone(), None);
14731473
// No need to collect tokens for this simple check.
14741474
parser
1475-
.parse_item(ForceCollect::No)
1475+
.parse_item(ForceCollect::No, AllowConstBlockItems::No)
14761476
.expect("failed to reparse item")
14771477
.expect("an actual item")
14781478
}

compiler/rustc_expand/src/expand.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ use rustc_hir::Target;
2525
use rustc_hir::def::MacroKinds;
2626
use rustc_hir::limit::Limit;
2727
use rustc_parse::parser::{
28-
AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
29-
token_descr,
28+
AllowConstBlockItems, AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser,
29+
RecoverColon, RecoverComma, token_descr,
3030
};
3131
use rustc_session::Session;
3232
use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
@@ -1099,7 +1099,7 @@ pub fn parse_ast_fragment<'a>(
10991099
Ok(match kind {
11001100
AstFragmentKind::Items => {
11011101
let mut items = SmallVec::new();
1102-
while let Some(item) = this.parse_item(ForceCollect::No)? {
1102+
while let Some(item) = this.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? {
11031103
items.push(item);
11041104
}
11051105
AstFragment::Items(items)

compiler/rustc_expand/src/proc_macro.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustc_ast::tokenstream::TokenStream;
22
use rustc_errors::ErrorGuaranteed;
33
use rustc_middle::ty::{self, TyCtxt};
4-
use rustc_parse::parser::{ForceCollect, Parser};
4+
use rustc_parse::parser::{AllowConstBlockItems, ForceCollect, Parser};
55
use rustc_session::Session;
66
use rustc_session::config::ProcMacroExecutionStrategy;
77
use rustc_span::profiling::SpannedEventArgRecorder;
@@ -160,7 +160,10 @@ impl MultiItemModifier for DeriveProcMacro {
160160
let mut items = vec![];
161161

162162
loop {
163-
match parser.parse_item(ForceCollect::No) {
163+
match parser.parse_item(
164+
ForceCollect::No,
165+
if is_stmt { AllowConstBlockItems::No } else { AllowConstBlockItems::Yes },
166+
) {
164167
Ok(None) => break,
165168
Ok(Some(item)) => {
166169
if is_stmt {

0 commit comments

Comments
 (0)