about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-07-17 19:02:06 +0000
committerMichael Goulet <michael@errs.io>2023-07-19 16:24:58 +0000
commit719797949ab1122d92a608b3f11f3321166b02eb (patch)
treee600ead2aa846e23b0b8bf2c2464d44653d1f2bf
parent11da267fdb17371d60e6f555d4bcf35bf765d982 (diff)
downloadrust-719797949ab1122d92a608b3f11f3321166b02eb.tar.gz
rust-719797949ab1122d92a608b3f11f3321166b02eb.zip
Fix inline_const with interpolated block
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs3
-rw-r--r--tests/ui/inline-const/interpolated.rs32
2 files changed, 34 insertions, 1 deletions
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index e4d843b7c8b..2e1a61e634e 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1210,7 +1210,8 @@ impl<'a> Parser<'a> {
     fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const {
         // Avoid const blocks and const closures to be parsed as const items
         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)
         {
             Const::Yes(self.prev_token.uninterpolated_span())
diff --git a/tests/ui/inline-const/interpolated.rs b/tests/ui/inline-const/interpolated.rs
new file mode 100644
index 00000000000..3fcc621c946
--- /dev/null
+++ b/tests/ui/inline-const/interpolated.rs
@@ -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() {}