Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1524,7 +1524,7 @@ impl<'a> Parser<'a> {
},
)
} else if this.check_inline_const(0) {
this.parse_const_block(lo)
this.parse_const_block(lo, false)
} else if this.may_recover() && this.is_do_catch_block() {
this.recover_do_catch()
} else if this.is_try_block() {
Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_parse/src/parser/mod.rs
Copy link
Member

@fmease fmease Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awkwardly, some cases of inline const pats can only be caught pre-expansion and some can only be caught post-expansion. #149667 switched from only rejecting the former to only rejecting the latter.

The existence of PatKind::Expr / $e:expr being allowed to be inserted into pats continues to make me sad.

Diagnostic stashing+stealing would allow us to use the diagnostic note (use a named …) from AST lowering again, instead of duplicating it here … at the cost of not showing this help under #[cfg(false)]. Might be overkill tho (and it definitely shouldn't be done in this PR).

Original file line number Diff line number Diff line change
Expand Up @@ -1270,7 +1270,7 @@ impl<'a> Parser<'a> {
}

/// Parses inline const expressions.
fn parse_const_block(&mut self, span: Span) -> PResult<'a, Box<Expr>> {
fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, Box<Expr>> {
self.expect_keyword(exp!(Const))?;
let (attrs, blk) = self.parse_inner_attrs_and_block(None)?;
let anon_const = AnonConst {
Expand All @@ -1279,7 +1279,18 @@ impl<'a> Parser<'a> {
mgca_disambiguation: MgcaDisambiguation::AnonConst,
};
let blk_span = anon_const.value.span;
let kind = ExprKind::ConstBlock(anon_const);
let kind = if pat {
let guar = self
.dcx()
.struct_span_err(blk_span, "const blocks cannot be used as patterns")
.with_help(
"use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead",
)
.emit();
ExprKind::Err(guar)
} else {
ExprKind::ConstBlock(anon_const)
};
Ok(self.mk_expr_with_attrs(span.to(blk_span), kind, attrs))
}

Expand Down
8 changes: 3 additions & 5 deletions compiler/rustc_parse/src/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -785,10 +785,8 @@ impl<'a> Parser<'a> {
} else if self.eat_keyword(exp!(Box)) {
self.parse_pat_box()?
} else if self.check_inline_const(0) {
// Parse `const pat`.
// NOTE: This will always error later during AST lowering because
// inline const cannot be used as patterns.
let const_expr = self.parse_const_block(lo.to(self.token.span))?;
// Parse `const pat`
let const_expr = self.parse_const_block(lo.to(self.token.span), true)?;

if let Some(re) = self.parse_range_end() {
self.parse_pat_range_begin_with(const_expr, re)?
Expand Down Expand Up @@ -1283,7 +1281,7 @@ impl<'a> Parser<'a> {
.then_some(self.prev_token.span);

let bound = if self.check_inline_const(0) {
self.parse_const_block(self.token.span)
self.parse_const_block(self.token.span, true)
} else if self.check_path() {
let lo = self.token.span;
let (qself, path) = if self.eat_lt() {
Expand Down
22 changes: 11 additions & 11 deletions tests/ui/inline-const/in-pat-recovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,63 @@
fn main() {
match 1 {
const { 1 + 7 } => {}
//~^ ERROR arbitrary expressions aren't allowed in patterns
//~^ ERROR const blocks cannot be used as patterns
2 => {}
_ => {}
}

match 5 {
const { 1 } ..= 10 => {}
//~^ ERROR arbitrary expressions aren't allowed in patterns
//~^ ERROR const blocks cannot be used as patterns
_ => {}
}

match 5 {
1 ..= const { 10 } => {}
//~^ ERROR arbitrary expressions aren't allowed in patterns
//~^ ERROR const blocks cannot be used as patterns
_ => {}
}

match 5 {
const { 1 } ..= const { 10 } => {}
//~^ ERROR arbitrary expressions aren't allowed in patterns
//~| ERROR arbitrary expressions aren't allowed in patterns
//~^ ERROR const blocks cannot be used as patterns
//~| ERROR const blocks cannot be used as patterns
_ => {}
}

match 5 {
const { 1 } .. 10 => {}
//~^ ERROR arbitrary expressions aren't allowed in patterns
//~^ ERROR const blocks cannot be used as patterns
_ => {}
}

match 5 {
1 .. const { 10 } => {}
//~^ ERROR arbitrary expressions aren't allowed in patterns
//~^ ERROR const blocks cannot be used as patterns
_ => {}
}

match 5 {
const { 1 + 2 } ..= 10 => {}
//~^ ERROR arbitrary expressions aren't allowed in patterns
//~^ ERROR const blocks cannot be used as patterns
_ => {}
}

match 5 {
1 ..= const { 5 + 5 } => {}
//~^ ERROR arbitrary expressions aren't allowed in patterns
//~^ ERROR const blocks cannot be used as patterns
_ => {}
}

match 5 {
const { 3 } .. => {}
//~^ ERROR arbitrary expressions aren't allowed in patterns
//~^ ERROR const blocks cannot be used as patterns
_ => {}
}

match 5 {
..= const { 7 } => {}
//~^ ERROR arbitrary expressions aren't allowed in patterns
//~^ ERROR const blocks cannot be used as patterns
_ => {}
}
}
66 changes: 33 additions & 33 deletions tests/ui/inline-const/in-pat-recovery.stderr
Original file line number Diff line number Diff line change
@@ -1,88 +1,88 @@
error: arbitrary expressions aren't allowed in patterns
--> $DIR/in-pat-recovery.rs:6:9
error: const blocks cannot be used as patterns
--> $DIR/in-pat-recovery.rs:6:15
|
LL | const { 1 + 7 } => {}
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

error: arbitrary expressions aren't allowed in patterns
--> $DIR/in-pat-recovery.rs:13:9
error: const blocks cannot be used as patterns
--> $DIR/in-pat-recovery.rs:13:15
|
LL | const { 1 } ..= 10 => {}
| ^^^^^^^^^^^
| ^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

error: arbitrary expressions aren't allowed in patterns
--> $DIR/in-pat-recovery.rs:19:15
error: const blocks cannot be used as patterns
--> $DIR/in-pat-recovery.rs:19:21
|
LL | 1 ..= const { 10 } => {}
| ^^^^^^^^^^^^
| ^^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

error: arbitrary expressions aren't allowed in patterns
--> $DIR/in-pat-recovery.rs:25:9
error: const blocks cannot be used as patterns
--> $DIR/in-pat-recovery.rs:25:15
|
LL | const { 1 } ..= const { 10 } => {}
| ^^^^^^^^^^^
| ^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

error: arbitrary expressions aren't allowed in patterns
--> $DIR/in-pat-recovery.rs:25:25
error: const blocks cannot be used as patterns
--> $DIR/in-pat-recovery.rs:25:31
|
LL | const { 1 } ..= const { 10 } => {}
| ^^^^^^^^^^^^
| ^^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

error: arbitrary expressions aren't allowed in patterns
--> $DIR/in-pat-recovery.rs:32:9
error: const blocks cannot be used as patterns
--> $DIR/in-pat-recovery.rs:32:15
|
LL | const { 1 } .. 10 => {}
| ^^^^^^^^^^^
| ^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

error: arbitrary expressions aren't allowed in patterns
--> $DIR/in-pat-recovery.rs:38:14
error: const blocks cannot be used as patterns
--> $DIR/in-pat-recovery.rs:38:20
|
LL | 1 .. const { 10 } => {}
| ^^^^^^^^^^^^
| ^^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

error: arbitrary expressions aren't allowed in patterns
--> $DIR/in-pat-recovery.rs:44:9
error: const blocks cannot be used as patterns
--> $DIR/in-pat-recovery.rs:44:15
|
LL | const { 1 + 2 } ..= 10 => {}
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

error: arbitrary expressions aren't allowed in patterns
--> $DIR/in-pat-recovery.rs:50:15
error: const blocks cannot be used as patterns
--> $DIR/in-pat-recovery.rs:50:21
|
LL | 1 ..= const { 5 + 5 } => {}
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

error: arbitrary expressions aren't allowed in patterns
--> $DIR/in-pat-recovery.rs:56:9
error: const blocks cannot be used as patterns
--> $DIR/in-pat-recovery.rs:56:15
|
LL | const { 3 } .. => {}
| ^^^^^^^^^^^
| ^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

error: arbitrary expressions aren't allowed in patterns
--> $DIR/in-pat-recovery.rs:62:13
error: const blocks cannot be used as patterns
--> $DIR/in-pat-recovery.rs:62:19
|
LL | ..= const { 7 } => {}
| ^^^^^^^^^^^
| ^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

Expand Down
12 changes: 12 additions & 0 deletions tests/ui/inline-const/reject-const-block-pat-pre-expansion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/152499>: reject inline const
//! patterns pre-expansion when possible.
macro_rules! analyze { ($p:pat) => {}; }
analyze!(const { 0 });
//~^ ERROR: const blocks cannot be used as patterns

#[cfg(false)]
fn scope() { let const { 0 }; }
//~^ ERROR: const blocks cannot be used as patterns

fn main() {}
18 changes: 18 additions & 0 deletions tests/ui/inline-const/reject-const-block-pat-pre-expansion.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error: const blocks cannot be used as patterns
--> $DIR/reject-const-block-pat-pre-expansion.rs:9:24
|
LL | fn scope() { let const { 0 }; }
| ^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

error: const blocks cannot be used as patterns
--> $DIR/reject-const-block-pat-pre-expansion.rs:5:16
|
LL | analyze!(const { 0 });
| ^^^^^
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead

error: aborting due to 2 previous errors

Loading