Skip to content

Want better error message for attempted hygiene violation, binding in macro #149604

@ijackson

Description

@ijackson

Code

macro_rules! let_it { {} => { let it = (); } }
macro_rules! print_it { {} => { println!("{:?}", it); } }

fn main() {
    let_it!();
    let () = it;
    print_it!();
}

Current output

error[E0425]: cannot find value `it` in this scope
 --> src/main.rs:6:14
  |
6 |     let () = it;
  |              ^^ not found in this scope

error[E0425]: cannot find value `it` in this scope
 --> src/main.rs:2:50
  |
2 | macro_rules! print_it { {} => { println!("{:?}", it); } }
  |                                                  ^^ not found in this scope
...
7 |     print_it!();
  |     ----------- in this macro invocation
  |
  = note: this error originates in the macro `print_it` (in Nightly builds, run with -Z macro-backtrace for more info)

Desired output

error[E0425]: cannot find value `it` in this scope
 --> src/main.rs:6:14
  |
6 |     let () = it;
  |              ^^ not found in this scope

help: An identifier with the same name is defined here, but is not accessible due to macro hygiene
1 | macro_rules! let_it { {} => { let it = (); } }
  |                                   ^^ inaccessible definition 

error[E0425]: cannot find value `it` in this scope
 --> src/main.rs:2:50
  |
2 | macro_rules! print_it { {} => { println!("{:?}", it); } }
  |                                                  ^^ not found in this scope
...
7 |     print_it!();
  |     ----------- in this macro invocation
  |

help: An identifier with the same name is defined here, but is not accessible due to macro hygiene
1 | macro_rules! let_it { {} => { let it = (); } }
  |                                   ^^ inaccessible definition 

  = note: this error originates in the macro `print_it` (in Nightly builds, run with -Z macro-backtrace for more info)

Rationale and extra context

See #148580

Other cases

See #148580 in which I first suggested such a hint. The example I gave there https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=1ee109560f0d9e2f216a02e346679f1c binds outside the macro and tries to use from inside. This was implemented in #148612 (thanks @chenyukang !)

However, here we have the binding in the macro, which is also forbidden by hygiene. Apparently the implemnetation in #148612 doesn't cover this case.

Rust Version

Today's nightly on the Rust playground.

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=9fb1d5c7091fc5b8572aa30e9ae2f039

Also locally:

rustc 1.93.0-nightly (646a3f8c1 2025-12-02)
binary: rustc
commit-hash: 646a3f8c15baefb98dc6e0c1c1ba3356db702d2a
commit-date: 2025-12-02
host: x86_64-unknown-linux-gnu
release: 1.93.0-nightly
LLVM version: 21.1.5

Anything else?

CC @JonathanBrouwer

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsA-hygieneArea: Macro hygieneA-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)D-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.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