1

I'm trying to write some macros that work in nostd environment as well as in std environment. In order to do so I have this kind of code in proc macro crate:

#[cfg(not(feature = "alloc"))]
{
    quote!(err.message = Some(::std::borrow::Cow::from(#m));)
}
#[cfg(feature = "alloc")]
{
    quote!(err.message = Some(::alloc::borrow::Cow::from(#m));)
}

This correctly produces the code that uses alloc when alloc feature is enabled, but the compiler complains

error[E0433]: failed to resolve: could not find `alloc` in the list of imported crates

Of course the reason is that the macro expansion is missing

extern crate alloc;

But adding that is a problem. Since it's a procedural derive macro, the extern crate will be added on each derive call. How can I refer to an extern crate in macro expansion? Using $crate does not seem to work inside quote!.

digital illusion
  • 497
  • 3
  • 19

1 Answers1

3

You can wrap the expansion in a block, then you can define alloc multiple times.

Another common practice for proc macros that need auxiliary types is to create a crate that provides them, and reexport the macro from it. E.g. create mycrate and mycrate-macros. Then you can get rid of the whole alloc feature if you only need alloc-accessible types, like:

#![no_std]

extern crate alloc;

#[doc(inline)]
pub use mycrate_macros::my_macro;

#[doc(hidden)]
pub use alloc:borrow::Cow;

Then in the macro refer to ::my_crate::Cow.

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77