rust-lang / rust-analyzer

A Rust compiler front-end for IDEs
https://rust-analyzer.github.io/
Apache License 2.0
14.2k stars 1.59k forks source link

False macro expansion error in `lazy_static_include_bytes` #11521

Open matklad opened 2 years ago

matklad commented 2 years ago

This macro call fails to expand for me:

https://github.com/near/nearcore/blob/d338e91390c9b3ed422c66dbfd2548bcc8282249/genesis-tools/genesis-csv-to-json/src/csv_parser.rs#L345-L347

I think this is related to $vis token producing an empty match, as the following works:

pub RES => "res/test_accounts.csv"

Veykril commented 2 years ago

smaller repro:

macro_rules! m {
    (($tt:tt)) => {
        stringify!($tt)
    };
    ($vis:vis $name:ident) => {
        m!(($vis))
    };
}
const _: &str = m$0!(foo);

Turns out tt fragments can capture empty vis captures

matklad commented 2 years ago

:speak_no_evil:

Veykril commented 2 years ago

Ye I don't think there is much we can do here right now? I assume rust doesn't need to convert intermediate expansions back into proper ASTs like we do 😬 so this requires us to have an empty ast node or something similar.

I demand a cursed label for macro related issues like these

Veykril commented 2 years ago

Oh now thinking about that, it makes a lot of sense that it works this way, since macro captures that arent tt, ident or lifetime are opaque, so capturing an empty token tree should be opaque to following macros 🙃. Ye I am really not sure how we can get out of this aside from modifying our syntax trees... lovely.

matklad commented 2 years ago

I think modifying syntax trees is ok: we support $crate in the ast for example.

One worry I have is that we lightly enforce an invariat that there are no nodes of length zero, and, if we allow them, I expect a tonne of subtle bugs to surface over the years.

So perhaps we can say that, in the ast, this node contains a single space?