vx-lang / vx-lang/Vx

macro_rules: no repetition and no tt fragment, so a variadic macro cannot be written

Open
#565 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

core-lang enhancement
Dominant language
Rust
Stars
14
Forks
2
Avg merge
13h 13m
Merged PRs (30d)
70

Description

What is missing

A macro_rules matcher cannot describe a list. Two limits together cause this.

No repetition operator. $(...),* is not supported:

macro_rules count { ($($x : expr),*) => {
    0
  }; }

fn main() -> i32 {
  return count!(1, 2, 3);
}
Macro expansion failed: No matching rule found for macro count

Three fragment kinds. src/parser/macro_expand.rs:189 accepts expr, ty, and ident. There
is no tt, so a rule cannot capture an arbitrary token and pass the rest along, which is how a
recursive macro walks a list.

A macro can take a fixed number of arguments, and macros can nest and recurse -- item-position
expansion drains a worklist with a 64-round cap. What cannot be written is a rule whose shape
depends on how many arguments arrived.

Why it matters

vec! is the proof. It accepts any number of elements, and it is hardcoded in the expander
(src/parser/macro_expand.rs:538) rather than written in the macro language. A user cannot write
their own vec!, or any variadic builder, or a println!-shaped macro over a list of arguments.

It also closes the last route to compile-time repetition. Recursion through the const evaluator has
its own blockers (#560), const generic recursion does not parse (#564), and a macro that decomposes
a list one element at a time needs the two things above.

What needs to exist

  • Repetition in matchers and in transcribers: $( ... )sep* and $( ... )sep+, with the captured
    fragments bound per repetition and expanded in the transcriber.
  • A tt fragment kind, so a rule can capture one token tree and recurse on the remainder.
  • A recursion limit with a message, which item-position expansion already has and which the
    expression-position path should share.

Once these exist, vec! should move out of the expander and into the macro language, as the test
that they are enough.

Tests to add

  • A user-written variadic macro over zero, one, and several arguments.
  • A recursive macro that consumes a list one tt at a time and terminates on the empty rule.
  • A macro whose expansion depends on the argument count, so a rule matching the wrong arity goes
    red.
  • A fail fixture for a macro that recurses without terminating, checking the message.

Related: #560, #564.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/parser/macro_expand.rs, especially the fragment handling at line 189, the hardcoded vec! expansion around line 538, and the existing item-position worklist and recursion limit. Add the requested repetition, tt handling, expression-position limit behavior, and tests for empty and variadic inputs, recursive termination, arity mismatch, and nontermination diagnostics; done includes moving vec! into the macro language.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.