Daniel Fath
Daniel Fath

Reputation: 18069

Using $crate in Rust's procedural macros?

I know what the $crate variable is, but as far as I can tell, it can't be used inside procedural macros. Is there another way to achieve a similar effect?

I have an example that roughly requires me to write something like this using quote and nightly Rust

quote!(
     struct Foo {
        bar: [SomeTrait;#len]
     }
)

I need to make sure SomeTrait is in scope (#len is referencing an integer outside the scope of the snippet).

I am using procedural macros 2.0 on nightly using quote and syn because proc-macro-hack didn't work for me. This is the example I'm trying to generalize.

Upvotes: 32

Views: 9226

Answers (5)

Alyssa Haroldsen
Alyssa Haroldsen

Reputation: 3731

Since Rust 1.45, you can use Span::mixed_site as an Idents span to use $crate directly and avoid conflicts with local variables.

quote_spanned!(Span::mixed_site()=>
     struct Foo {
        bar: [$crate::SomeTrait; #len]
     }
)

Upvotes: -1

x1hgg1x
x1hgg1x

Reputation: 125

You can wrap your proc-macro inside a declarative macro, and pass the $crate identifier to your proc-macro for reuse (see this commit for example). It will create a proc_macro::Ident value with the special $crate identifier.

Note that you cannot manually create such an identifier, since $ is normally invalid inside identifiers.

Upvotes: 1

Gary Howe
Gary Howe

Reputation: 191

Since Rust 1.34, you can use extern crate self as my_crate, and use my_crate::Foo instead of $crate::Foo.

https://github.com/rust-lang/rust/issues/54647

https://github.com/rust-lang/rust/pull/57407

(Credit: Neptunepink ##rust irc.freenode.net)

Upvotes: 12

dhardy
dhardy

Reputation: 12164

In Edition 2015 (classic Rust), you can do this (but it's hacky):

  • use ::defining_crate::SomeTrait in the macro
  • within third-party crates depending on defining_crate, the above works fine
  • within defining_crate itself, add a module in the root:

    mod defining_crate { pub use super::*; }

In Edition 2018 even more hacky solutions are required (see this issue), though #55275 may give us a simple workaround.

Upvotes: 2

Ekleog
Ekleog

Reputation: 1054

Based on replies from https://github.com/rust-lang/rust/issues/38356#issuecomment-412920528, it looks like there is no way to do this (as of 2018-08), neither to refer to the proc-macro crate nor to refer to any other crate unambiguously.

Upvotes: 4

Related Questions