Store macro matchers properly
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 2.9k
- Forks
- 231
- Avg merge
- 19h 55m
- Merged PRs (30d)
- 67
Description
When forwarding a matched fragment to another macro-by-example, matchers in the second macro will see an opaque AST of the fragment type. The second macro can't use literal tokens to match the fragments in the matcher, only a fragment specifier of the same type. The ident, lifetime, and tt fragment types are an exception, and can be matched by literal tokens. The following illustrates this restriction
macro_rules! foo {
($l:expr) => { bar!($l); }
// ERROR: ^^ no rules expected this token in macro call
}
macro_rules! bar {
(3) => {}
}
foo!(3);
The following illustrates how tokens can be directly matched after matching a tt fragment:
// compiles OK
macro_rules! foo {
($l:tt) => { bar!($l); }
}
macro_rules! bar {
(3) => {}
}
foo!(3);
From https://doc.rust-lang.org/reference/macros-by-example.html
- We need to be able to store the macro matcher properly, either as an opaque
Expror equivalent or as a specific case - We need to be able to match recursively on
ident,lifetimeandttfragments
Small resolver stress test
macro_rules! foo0 {
($a:tt) => {
foo1!($a)
}
}
macro_rules! foo1 {
($a:tt) => {
foo2!($a)
}
}
macro_rules! foo2 {
($a:tt) => {
foo3!($a)
}
}
macro_rules! foo3 {
($a:tt) => {
foo4!($a)
}
}
macro_rules! foo4 {
($a:tt) => {
foo5!($a)
}
}
macro_rules! foo5 {
($a:tt) => {
foo6!($a)
}
}
macro_rules! foo6 {
($a:tt) => {
foo7!($a)
}
}
macro_rules! foo7 {
($a:tt) => {
foo8!($a)
}
}
macro_rules! foo8 {
($a:tt) => {
foo9!($a)
}
}
macro_rules! foo9 {
($a:tt) => {
foo10!($a)
}
}
macro_rules! foo10 {
($a:tt) => {
foo11!($a)
}
}
macro_rules! foo11 {
($a:tt) => {
foo12!($a)
}
}
macro_rules! foo12 {
($a:tt) => {
foo13!($a)
}
}
macro_rules! foo13 {
($a:tt) => {
foo14!($a)
}
}
macro_rules! foo14 {
($a:tt) => {
foo15!($a)
}
}
macro_rules! foo15 {
($a:tt) => {
foo16!($a)
}
}
macro_rules! foo16 {
($a:tt) => {
foo17!($a)
}
}
macro_rules! foo17 {
($a:tt) => {
foo18!($a)
}
}
macro_rules! foo18 {
($a:tt) => {
foo19!($a)
}
}
macro_rules! foo19 {
($a:tt) => {
foo20!($a)
}
}
macro_rules! foo20 {
($a:tt) => {
foo21!($a)
}
}
macro_rules! foo21 {
($a:tt) => {
foo22!($a)
}
}
macro_rules! foo22 {
($a:tt) => {
foo23!($a)
}
}
macro_rules! foo23 {
($a:tt) => {
foo24!($a)
}
}
macro_rules! foo24 {
($a:tt) => {
foo25!($a)
}
}
macro_rules! foo25 {
($a:tt) => {
foo26!($a)
}
}
macro_rules! foo26 {
($a:tt) => {
foo27!($a)
}
}
macro_rules! foo27 {
($a:tt) => {
foo28!($a)
}
}
macro_rules! foo28 {
($a:tt) => {
foo29!($a)
}
}
macro_rules! foo29 {
($a:tt) => {
foo30!($a)
}
}
macro_rules! foo30 {
($a:tt) => {
foo31!($a)
}
}
macro_rules! foo31 {
($a:tt) => {
foo32!($a)
}
}
macro_rules! foo32 {
($a:tt) => {
foo33!($a)
}
}
macro_rules! foo33 {
($a:tt) => {
foo34!($a)
}
}
macro_rules! foo34 {
($a:tt) => {
foo35!($a)
}
}
macro_rules! foo35 {
($a:tt) => {
foo36!($a)
}
}
macro_rules! foo36 {
($a:tt) => {
foo37!($a)
}
}
macro_rules! foo37 {
($a:tt) => {
foo38!($a)
}
}
macro_rules! foo38 {
($a:tt) => {
foo39!($a)
}
}
macro_rules! foo39 {
($a:tt) => {
foo40!($a)
}
}
macro_rules! foo40 {
($a:tt) => {
foo41!($a)
}
}
macro_rules! foo41 {
($a:tt) => {
foo42!($a)
}
}
macro_rules! foo42 {
($a:tt) => {
foo43!($a)
}
}
macro_rules! foo43 {
($a:tt) => {
foo44!($a)
}
}
macro_rules! foo44 {
($a:tt) => {
foo45!($a)
}
}
macro_rules! foo45 {
($a:tt) => {
foo46!($a)
}
}
macro_rules! foo46 {
($a:tt) => {
foo47!($a)
}
}
macro_rules! foo47 {
($a:tt) => {
foo48!($a)
}
}
macro_rules! foo48 {
($a:tt) => {
foo49!($a)
}
}
macro_rules! foo49 {
($a:tt) => {
foo50!($a)
}
}
macro_rules! foo50 {
($a:tt) => {
foo51!($a)
}
}
macro_rules! foo51 {
($a:tt) => {
foo52!($a)
}
}
macro_rules! foo52 {
($a:tt) => {
foo53!($a)
}
}
macro_rules! foo53 {
($a:tt) => {
foo54!($a)
}
}
macro_rules! foo54 {
($a:tt) => {
foo55!($a)
}
}
macro_rules! foo55 {
($a:tt) => {
foo56!($a)
}
}
macro_rules! foo56 {
($a:tt) => {
foo57!($a)
}
}
macro_rules! foo57 {
($a:tt) => {
foo58!($a)
}
}
macro_rules! foo58 {
($a:tt) => {
foo59!($a)
}
}
macro_rules! foo59 {
($a:tt) => {
foo60!($a)
}
}
macro_rules! foo60 {
($a:tt) => {
foo61!($a)
}
}
macro_rules! foo61 {
($a:tt) => {
foo62!($a)
}
}
macro_rules! foo62 {
($a:tt) => {
foo63!($a)
}
}
macro_rules! foo63 {
($a:tt) => {
foo64!($a)
}
}
macro_rules! foo64 {
($a:tt) => {
foo65!($a)
}
}
macro_rules! foo65 {
($a:tt) => {
foo66!($a)
}
}
macro_rules! foo66 {
($a:tt) => {
foo67!($a)
}
}
macro_rules! foo67 {
($a:tt) => {
foo68!($a)
}
}
macro_rules! foo68 {
($a:tt) => {
foo69!($a)
}
}
macro_rules! foo69 {
($a:tt) => {
foo70!($a)
}
}
macro_rules! foo70 {
($a:tt) => {
foo71!($a)
}
}
macro_rules! foo71 {
($a:tt) => {
foo72!($a)
}
}
macro_rules! foo72 {
($a:tt) => {
foo73!($a)
}
}
macro_rules! foo73 {
($a:tt) => {
foo74!($a)
}
}
macro_rules! foo74 {
($a:tt) => {
foo75!($a)
}
}
macro_rules! foo75 {
($a:tt) => {
foo76!($a)
}
}
macro_rules! foo76 {
($a:tt) => {
foo77!($a)
}
}
macro_rules! foo77 {
($a:tt) => {
foo78!($a)
}
}
macro_rules! foo78 {
($a:tt) => {
foo79!($a)
}
}
macro_rules! foo79 {
($a:tt) => {
foo80!($a)
}
}
macro_rules! foo80 {
($a:tt) => {
foo81!($a)
}
}
macro_rules! foo81 {
($a:tt) => {
foo82!($a)
}
}
macro_rules! foo82 {
($a:tt) => {
foo83!($a)
}
}
macro_rules! foo83 {
($a:tt) => {
foo84!($a)
}
}
macro_rules! foo84 {
($a:tt) => {
foo85!($a)
}
}
macro_rules! foo85 {
($a:tt) => {
foo86!($a)
}
}
macro_rules! foo86 {
($a:tt) => {
foo87!($a)
}
}
macro_rules! foo87 {
($a:tt) => {
foo88!($a)
}
}
macro_rules! foo88 {
($a:tt) => {
foo89!($a)
}
}
macro_rules! foo89 {
($a:tt) => {
last!($a)
}
}
macro_rules! last {
(3) => {
println!("fizz")
};
(5) => {
println!("buzz")
};
($any:tt) => {
println!(" :) ")
}
}
fn main() {
foo0!(3);
foo0!(5);
foo0!(6);
}
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.
Research direction
Use the macro_rules examples and the 90-level resolver stress test in this issue as reproductions. Start by tracing gccrs's macro matcher storage and recursive matching paths, comparing expr with tt behavior and the ident, lifetime, and tt exceptions. Done when forwarded fragments support the described literal matches and the stress test preserves the 3, 5, and 6 cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100