Skip to content

let-else does not respect macro_rules expr metavariable grouping #147899

@theemathas

Description

@theemathas

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

No one assigned

    Labels

    A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-parserArea: The lexing & parsing of Rust source code to an ASTC-bugCategory: This is a bug.T-compilerRelevant 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.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions