rust-lang / rust-lang/rust-analyzer
`macro_rules!` emitted by a path-qualified cross-crate call is not added to textual scope
@Aditya-PS-05 is already working on this.
Since Sep 3, 2026.
- Dominant language
- Rust
- Stars
- 16.9k
- Forks
- 2.2k
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 72
Description
rust-analyzer version: 1.100.0-nightly (9085017 2026-08-30) (also 1.98.0, 1.99.0-beta.3)
rustc version: 1.98.0 (88d9e12ae 2026-08-18)
editor or extension: Cursor v3.18.9, Extension version 0.4.3032 (Pre-release, same with release)
relevant settings: None
The issue
Crate generator exports a macro that expands to a macro_rules! foo definition. When a consumer invokes that generator by qualified path (generator::gen_foo!(...)), rust-analyzer expands the generator but never registers the generated foo in the module's textual scope, so every later foo!(...) is unresolved macro. rustc resolves it and the code runs.
Invoking the same generator unqualified via #[macro_use] extern crate generator; works in rust-analyzer. So this is not nested macro_rules! in general, and not a rustc/rust-analyzer hygiene disagreement, it is specific to the qualified call form.
Reproducing code
Workspace with three crates. consumer_qualified and consumer_macro_use differ only in how they invoke gen_foo!.
Workspace Cargo.toml
[workspace]
resolver = "3"
members = ["generator", "consumer_qualified", "consumer_macro_use"]
generator/Cargo.toml
[package]
name = "generator"
version = "0.0.0"
edition = "2024"
generator/src/lib.rs
#[macro_export]
macro_rules! gen_foo {
() => {
macro_rules! foo {
() => {
42
};
}
};
}
consumer_qualified/Cargo.toml
[package]
name = "consumer_qualified"
version = "0.0.0"
edition = "2024"
[dependencies]
generator = { path = "../generator" }
consumer_qualified/src/inner.rs
generator::gen_foo!();
consumer_qualified/src/lib.rs
#[macro_use]
mod inner;
pub fn call() -> u32 {
foo!()
}
#[cfg(test)]
mod tests {
#[test]
fn generated_macro_runs() {
assert_eq!(super::call(), 42);
}
}
consumer_macro_use/Cargo.toml
[package]
name = "consumer_macro_use"
version = "0.0.0"
edition = "2024"
[dependencies]
generator = { path = "../generator" }
consumer_macro_use/src/inner.rs
gen_foo!();
consumer_macro_use/src/lib.rs
#[macro_use]
extern crate generator;
#[macro_use]
mod inner;
pub fn call() -> u32 {
foo!()
}
#[cfg(test)]
mod tests {
#[test]
fn generated_macro_runs() {
assert_eq!(super::call(), 42);
}
}
Expected behavior
Both consumers behave the same since both compile and pass the tests
Actual
In the IDE, consumer_qualified call() is marked as error expected u32, found () (which is the consequence of the not expanded macro).
When running rust-analyzer diagnostics . it produces diagnostics (filtered):
consumer_qualified/src/lib.rs: unresolved-macro-call: unresolved macro `foo!`
consumer_qualified/src/lib.rs: E0308: expected u32, found ()
while silent about consumer_macro_use.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.