dtolnay / proc-macro-workshop

Learn to write Rust procedural macros  [Rust Latam conference, Montevideo Uruguay, March 2019]
Apache License 2.0
4.13k stars 1.04k forks source link

Getting the correct span for multi-segment Path #72

Open shouya opened 5 months ago

shouya commented 5 months ago

Hi,

I spent a long time tracing down a bug in my implementation of the sorted macro against the 06-pattern-path test. Namely, my output always looked like this:

error: Error::Fmt should sort before Error::Io
  --> main.rs:23:7
   |
23 |       Error::Fmt(e) => write!(f, "{}", e),
   |       ^^^^^

where the error span is just Error instead of the expected Error::Fmt. I checked my code to made sure in my code that it's indeed the path's span being stored and emitted instead of the ident's. It's even more confusing because cargo expand gives the expected output whereas the cargo test and cargo run gives different answer.

After more debugging and searching I finally stumbled upon this issue. So after switching my toolchain from stable to nightly, the test passes as expected. Now I see it's because the stable proc-macro doesn't allow joining of spans, thus only the first token of the syntax tree is returned upon calling the Spanned::span function.

I think it may be good to indicate this trick somewhere in note since it's probably not a trivial bug. Anyway, to the future learners who had their head scratched hard for this error, I hope this issue can be helpful :)

shouya commented 5 months ago

Alternatively, instead of storing the Span, it's also possible to store the Path in its original form. Then one can use Error::new_spanned on the Path to create an error message spanning multiple tokens.