1
Fork 0

Rollup merge of #113803 - compiler-errors:const-interp-block, r=fee1-dead

Fix inline_const with interpolated block

Interpolation already worked when we had a `const $block` that wasn't a statement expr:

```
fn foo() {
  let _ = const $block;
}
```

But it was failing when the const block was in statement expr position:

```
fn foo() {
  const $block;
}
```

... because of a bug in a check for const items. This fixes that.

---

cc https://github.com/rust-lang/rust/pull/112953#issuecomment-1631354481, though I don't think this requires an FCP since it's already supported in exprs and seems to me to be fully a parser bug.
This commit is contained in:
Dylan DPC 2023-07-19 22:37:08 +05:30 committed by GitHub
commit 6c3cbcd333
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 1 deletions

View file

@ -1210,7 +1210,8 @@ impl<'a> Parser<'a> {
fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const { fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const {
// Avoid const blocks and const closures to be parsed as const items // Avoid const blocks and const closures to be parsed as const items
if (self.check_const_closure() == is_closure) if (self.check_const_closure() == is_closure)
&& self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace)) && !self
.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block())
&& self.eat_keyword_case(kw::Const, case) && self.eat_keyword_case(kw::Const, case)
{ {
Const::Yes(self.prev_token.uninterpolated_span()) Const::Yes(self.prev_token.uninterpolated_span())

View file

@ -0,0 +1,32 @@
// check-pass
#![feature(inline_const)]
// This used to be unsupported since the parser first tries to check if we have
// any nested items, and then checks for statements (and expressions). The heuristic
// that we were using to detect the beginning of a const item was incorrect, so
// this used to fail.
macro_rules! m {
($b:block) => {
fn foo() {
const $b
}
}
}
// This has worked since inline-consts were implemented, since the position that
// the const block is located at doesn't support nested items (e.g. because
// `let x = const X: u32 = 1;` is invalid), so there's no ambiguity parsing the
// inline const.
macro_rules! m2 {
($b:block) => {
fn foo2() {
let _ = const $b;
}
}
}
m!({});
m2!({});
fn main() {}