about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-12-18 02:11:55 +0000
committerMichael Goulet <michael@errs.io>2024-01-17 23:59:11 +0000
commitc1c7707238bd58242588d75a350def4ceb59c581 (patch)
tree6cbf52d5b5016e9a16c1584c30a7db2749a05f3b
parent6ae4cfbbb080cafea7f6be48ce47678ee057352c (diff)
downloadrust-c1c7707238bd58242588d75a350def4ceb59c581.tar.gz
rust-c1c7707238bd58242588d75a350def4ceb59c581.zip
Deny braced macro invocations in let-else
-rw-r--r--compiler/rustc_ast/src/util/classify.rs10
-rw-r--r--tests/ui/parser/bad-let-else-statement.rs25
-rw-r--r--tests/ui/parser/bad-let-else-statement.stderr28
3 files changed, 59 insertions, 4 deletions
diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs
index 65036bcdc36..098b8f2d6d0 100644
--- a/compiler/rustc_ast/src/util/classify.rs
+++ b/compiler/rustc_ast/src/util/classify.rs
@@ -2,7 +2,7 @@
 
 // Predicates on exprs and stmts that the pretty-printer and parser use
 
-use crate::ast;
+use crate::{ast, token::Delimiter};
 
 /// Does this expression require a semicolon to be treated
 /// as a statement? The negation of this: 'can this expression
@@ -59,8 +59,12 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
             | While(..)
             | ConstBlock(_) => break Some(expr),
 
-            // FIXME: These can end in `}`, but changing these would break stable code.
-            InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => {
+            MacCall(mac) => {
+                break (mac.args.delim == Delimiter::Brace).then_some(expr);
+            }
+
+            InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => {
+                // These should have been denied pre-expansion.
                 break None;
             }
 
diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs
index 7b927c89ba0..a42e8c41c2e 100644
--- a/tests/ui/parser/bad-let-else-statement.rs
+++ b/tests/ui/parser/bad-let-else-statement.rs
@@ -161,4 +161,29 @@ fn q() {
     };
 }
 
+fn r() {
+    let ok = format_args!("") else { return; };
+
+    let bad = format_args! {""} else { return; };
+    //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
+}
+
+fn s() {
+    macro_rules! a {
+        () => { {} }
+    }
+
+    macro_rules! b {
+        (1) => {
+            let x = a!() else { return; };
+        };
+        (2) => {
+            let x = a! {} else { return; };
+            //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
+        };
+    }
+
+    b!(1); b!(2);
+}
+
 fn main() {}
diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr
index 7cbda25e417..4ea924ddcb8 100644
--- a/tests/ui/parser/bad-let-else-statement.stderr
+++ b/tests/ui/parser/bad-let-else-statement.stderr
@@ -228,5 +228,31 @@ LL |         x
 LL ~     }) else {
    |
 
-error: aborting due to 17 previous errors
+error: right curly brace `}` before `else` in a `let...else` statement not allowed
+  --> $DIR/bad-let-else-statement.rs:167:31
+   |
+LL |     let bad = format_args! {""} else { return; };
+   |                               ^
+   |
+help: wrap the expression in parentheses
+   |
+LL |     let bad = (format_args! {""}) else { return; };
+   |               +                 +
+
+error: right curly brace `}` before `else` in a `let...else` statement not allowed
+  --> $DIR/bad-let-else-statement.rs:181:25
+   |
+LL |             let x = a! {} else { return; };
+   |                         ^
+...
+LL |     b!(1); b!(2);
+   |            ----- in this macro invocation
+   |
+   = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: wrap the expression in parentheses
+   |
+LL |             let x = (a! {}) else { return; };
+   |                     +     +
+
+error: aborting due to 19 previous errors