- Notifications
You must be signed in to change notification settings - Fork 13.9k
Open
Labels
A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-parserArea: The lexing & parsing of Rust source code to an ASTArea: The lexing & parsing of Rust source code to an ASTC-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.
Description
Code 1: let-else with &&
macro_rules! foo { ($e:expr) => { let true = $e else { return; }; } } fn main() { foo!(true && true); }error: a `&&` expression cannot be directly assigned in `let...else` --> src/main.rs:8:10 | 8 | foo!(true && true); | ^^^^^^^^^^^^ | help: wrap the expression in parentheses | 8 | foo!((true && true)); | + + Code 2: let-else with braces
#![allow(irrefutable_let_patterns)] macro_rules! foo { ($e:expr) => { let _ = $e else { return; }; } } struct Thing {} fn main() { foo!(Thing {}); }error: right curly brace `}` before `else` in a `let...else` statement not allowed --> src/main.rs:12:17 | 12 | foo!(Thing {}); | ^ | help: wrap the expression in parentheses | 12 | foo!((Thing {})); | + + I expected both of the above code snippets to compile. Instead, I got the above compile errors.
expr metavariables in macros are supposed to be opaque, and treated as if they're wrapped in "invisible parentheses". Therefore, I shouldn't need to wrap the expression in another layer of parentheses. However, let-else seems to not respect this grouping.
In contrast, if let correctly respects the grouping
if let with &&
This code correctly prints "works" three times.
macro_rules! foo { ($e:expr) => { if let false = $e { println!("works"); } else { unreachable!(); } } } fn main() { foo!(true && false); if let false = (true && false) { println!("works"); } else { unreachable!(); } if let false = true && false { unreachable!(); } else { println!("works"); } }if let with braces
This code compiles
#![allow(irrefutable_let_patterns)] macro_rules! foo { ($e:expr) => { if let _ = $e {} } } struct Thing {} fn main() { foo!(Thing {}); }Meta
Reproducible on the playground with version 1.92.0-nightly (2025-10-19 f04e3dfc87d7e2b6ad53)
Metadata
Metadata
Assignees
Labels
A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-parserArea: The lexing & parsing of Rust source code to an ASTArea: The lexing & parsing of Rust source code to an ASTC-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.