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.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions