We're stuck with a completely mysterious compilation problem with a procedural macro. By mysterious I mean that:
The error points at the name of the procedural macro in the #[derive] invocation, and even with -Zproc-macro-backtrace you cannot get any hint into the nature of the problem.
We know exactly which part of the generated code causes the error, and if we comment it out the compiler does not complain anymore, but the same exact code copied and pasted in another file compiles without problems.
If you want to see it happen, just
git clone https://github.com/vigna/epserde-rs
cd epserde-rs/epserde
RUSTFLAGS="-Zproc-macro-backtrace" cargo +nightly t --test test_types
If you want to see the code causing the problem, just
cargo expand --test test_types
and have a look at lines 1446-1463 and 1475-1492.
Any suggestion accepted. Are there diagnostic tools we are not aware of for procedural macros?
Just from looking at the snippet you posted above, this seems impossible. You can't have numbers as field names like you have in your Self::B and Self::C variants.
It's deliberately universal syntax to allow constructing/matching any type of declared struct or enum using braced syntax, introduced by RFC 1506 to allow macros to generate the same code structure regardless of the type's declaration syntax.
As I said, this compiles without a glitch if I copy-paste it and replace the function calls with constants. Which might mean the problem is with the function calls, but then I can't understand how...
Assuming it's accurate, I would suggest working on a minimal reproduction — modify your macro to produce only the erroneous code, and strip away all unnecessary elements even if this stops the macro from serving any useful purpose. Keep only the confusing part. That way, more people will be able to think about your now-smaller problem, and it makes good material for a bug report if this turns out to be a compiler bug.
We know because if you eliminate from the procedural macro the branches 0usize =>, etc., leaving just the tag =>, the error disappear. The problem is that we are unable to isolate the problem because, as I wrote above, in isolation it works .
the same exact code copied and pasted in another file compiles without problems.
The problem with this strategy is that text does not always reproduce an identical token stream, so it isn't an accurate test. Instead, make your macro simpler while checking that it still produces the syntactically-broken code. Keep going until you can't find anything to remove. Minimize your original code into a repro.
BTW, the problem persist even if you reduce the enum to just the variant A, so all branches 1=>usize, etc., disappear. This is why it's really weird—how can 0usize => Ok(Self::A {}), give a syntax error?
Great. Now start making your macro simpler. For example: convert it from a derive macro into a function-like macro, so it doesn't require a struct as input. Stop emitting an impl; just emit functions. Remove the use epserde:: — since this is a syntax error, you don't need the produced code to be valid any more than syntactically.
Make your large macro smaller by all possible means, not just reasonable ones that fit your original use-case. At the end of this process, if you actually follow it to the end, you will have something with which you can obtain understanding (or a bug report).
If you are trying to make integers into field names, you have to use Index, not a number literal. I don't know if you are already doing this, but it's a common mistake.
Printing the ouput of our quote! using eprintln!, one sees clearly the problem—A { {} }. For some reason, cargo expand turns this into A {}, making impossible to diagnose the problem.
UPDATE: After opening an issue, David Tolnay noticed that the same happens with cargo rustc -- -Zunpretty=expanded, so it's not a specific cargo-expand problem.