Change:
Given this test file: stable Rust errors like this: while on 1.36.0-nightly ( 2019-05-21) running on x86_64-unknown-linux-gnu:
caused by cc
Yay, we have a test case.
Hmm... interesting... yeah, I guess we have a test case. I will open a PR to revert and add the test case. Thanks ! But this raises a bigger point that has been growing on me for a while now: there are a ton of checks that are currently only done at macro invocation time (or are not done at all) that really would make more sense to do a macro definition time. Checking that the Kleene operator used in the body is the same as that in the matcher Checking that all meta-variables used in the body are defined and in scope Checking that all meta-variables used in the body are repeating at the right depth Checking that the body of a macro is actually valid rust syntax (to the extent that we can, anyway) So far, I have been holding off on attempting to fix these because they could involve building a whole language, and it seems that at some point we want to just use macros... Thoughts?
Opened
there are a ton of checks that are currently only done at macro invocation time (or are not done at all) that really would make more sense to do a macro definition time. If the defined macro produces an error with any possible input, then we should probably report it at definition time, at least as a quality of implementation measure (perhaps as a warning for a start). I have more confidence in reporting errors related to the macro definition language itself (meta-variables, repetitions, etc.), than in errors for produced tokens (which are not necessarily supposed to be Rust code, with eager expansion they may be consumed by another macro, for example).
Ok, makes sense. I will open another issue with these items so we can track them.

Discussion:
} LockstepIterSize::Contradiction(ref msg) => { <del> // This should never happen because the macro parser should generate // properly-sized matches for all meta-vars. cx.span_bug(seq.span(), &msg[..]); </del> <ins> // FIXME: this really ought to be caught at macro definition time... It // happens when two meta-variables are used in the same repetition in a // sequence, but they come from different sequence matchers and repeat // different amounts. cx.span_fatal(seq.span(), &msg[..]); </ins> } LockstepIterSize::Constraint(len, _) => {

// Is the repetition empty? if len == 0 { if seq.op == quoted::KleeneOp::OneOrMore { <del> // This should be impossible because the macro parser would not // match the given macro arm. cx.span_bug(sp.entire(), "this must repeat at least once"); </del> <ins> // FIXME: this really ought to be caught at macro definition // time... It happens when the Kleene operator in the matcher and // the body for the same meta-variable do not match. cx.span_fatal(sp.entire(), "this must repeat at least once"); </ins> } } else { // 0 is the initial counter (we have done 0 repretitions so far). `len`

LockstepIterSize::Constraint(r_len, _) if l_len == r_len => self, LockstepIterSize::Constraint(r_len, r_id) => { let msg = format!( <del> "inconsistent lockstep iteration:  '{}' has {} items, but '{}' has {}", </del> <ins> "meta-variable `{}` repeats {} times, but `{}` repeats {} times", </ins> l_id, l_len, r_id, r_len ); LockstepIterSize::Contradiction(msg)

<ins> // Regression test for issue #61033. macro_rules! test1 { ($x:ident, $($tt:tt)*) => { $($tt)+ } //~ERROR this must repeat at least once } fn main() { test1!(x,); } </ins>

<ins> error: this must repeat at least once --> $DIR/issue-61033-1.rs:4:34 | LL |     ($x:ident, $($tt:tt)*) => { $($tt)+ } |                                  ^^^^^ error: aborting due to previous error </ins>

<ins> // Regression test for issue #61033. macro_rules! test2 { ( $(* $id1:ident)* $(+ $id2:ident)* ) => { $( //~ERROR meta-variable `id1` repeats 2 times $id1 + $id2 // $id1 and $id2 may repeat different numbers of times )* } } fn main() { test2! { * a * b + a + b + c } } </ins>

<ins> error: meta-variable `id1` repeats 2 times, but `id2` repeats 3 times --> $DIR/issue-61033-2.rs:8:10 | LL |           $( |  __________^ LL | |             $id1 + $id2 // $id1 and $id2 may repeat different numbers of times LL | |         )* | |_________^ error: aborting due to previous error </ins>