Relation between proc_macro proc_macro2

Background: I've written a few macro_rules!, a few procedural (derive) macros, am working on a procedural (attribute) macro -- and this is now starting to bother me:

  1. what is the relation between proc_macro and proc_macro2

  2. what is the 'modern' way of using them (use both, use only proc_macro, use only proc_macro2) for writing procedural macros ?

proc_macro is a compiler build-in crate for writing procedural macros. You can't write a procedural macro crate, without specifying

proc-macro = true

in your Cargo.toml.

proc_macro2 on the other hand is a regular crate that works as a wrapper around proc_macro allowing you to (I) bring proc-macro-like functionality to other contexts like and and (II) make procedural macros unit testable. (I'm quoting the docs here).

Like I said above, you need proc_macro for writing macros. So the real question is, do you need proc_macro2. I personally have never written a procedural macro without it, as I use quote for constructing my return TokenStreams. quote::quote returns a proc_macro2::TokenStream.


proc_macro only works for proc macro crates, but proc_macro2 works for any crate.

A wrapper around the procedural macro API of the compiler’s proc_macro crate. This library serves two purposes:

  • Bring proc-macro-like functionality to other contexts like and Types from proc_macro are entirely specific to procedural macros and cannot ever exist in code outside of a procedural macro. Meanwhile proc_macro2 types may exist anywhere including non-macro code. By developing foundational libraries like syn and quote against proc_macro2 rather than proc_macro, the procedural macro ecosystem becomes easily applicable to many other use cases and we avoid reimplementing non-macro equivalents of those libraries.
  • Make procedural macros unit testable. As a consequence of being specific to procedural macros, nothing that uses proc_macro can be executed from a unit test. In order for helper libraries or components of a macro to be testable in isolation, they must be implemented using proc_macro2.