$crate in proc macro TokenStream

I'm working on a proc macro that will be a helper for a parent crate: https://github.com/zbraniecki/tinystr/blob/macros/macros/src/lib.rs#L17

It works really well and allows me to call it in the parent with no dependencies: https://github.com/zbraniecki/tinystr/blob/macros/tests/main.rs#L521

But when I try to add $crate:: to the TokenStream, it errors out with:

error: expected expression, found `$`
  --> tests/macros.rs:12:14
12 |     let x2 = tinystr4!("foo");
   |              ^^^^^^^^^^^^^^^^ expected expression
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error

error: could not compile `tinystr-macros`.

To learn more, run the command again with --verbose.

I thought it may be https://github.com/rust-lang/rust/pull/73345 which got fixed in Nightly recently, but no luck - same error in today's nightly.

Is there any way to use $crate in such scenario?

As far as I know, there’s no built-in way to do this, but you can read the CARGO_PKG_NAME environment variable to figure out whether it’s your crate or a downstream user’s that the macro is being expanded into.

I don't understand then. I have an older proc macro crate which uses proc-macro-hack and it does work with $crate - https://github.com/zbraniecki/unic-locale/blob/master/unic-langid-macros-impl/src/lib.rs#L18

Does it mean that proc-macro-hack does something special?

I’m admittedly not very experienced with proc macros, so I may be misremembering something. While searching for the Rust issue where I saw that this is a known problem, I ran across proc-macro-crate that has a more robust way to handle this.

I don't know, but I would assume that it outputs $crate verbatim, which is then handled by the declarative macro around the procedural macro. At least, that's how I understand that proc-macro-hack works, but I'm not 100% sure.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.