I am trying to write a procedural macro that performs different behavior based on a trait type, which the macro may not have access to. For example, given the following trait:
trait Bar {
type BarType;
}
I would like to be able to change macro behavior based on the chosen BarType
, even when my macro may not have direct access to it:
// This macro sees nothing about BarType
#[macro_option_1]
struct Foo {}
// this macro sees nothing about BarType
macro_option_2!(Foo);
// This location works but is not desirable
// #[working_macro_option]
impl Bar for Foo {
type BarType = Option<u32>;
}
A macro at working_macro_option
would have access to BarType
, but this location is not desirable (as my actual macro needs to work with multiple traits). So, my goal is to be able to use a macro that works at either macro_option_1
or macro_option_2
, which have no useful content available to parse.
I am hoping for a pattern along the lines of what quote_spanned
makes possible (link to example), but changing what the macro does in some way. So, I believe this needs to be something that's directly compilable, rather than something possible only in proc macros.
(this is unfortunately outside the scope of generics - my macro needs to create a function with a completely different signature based on type, for a C FFI)
Edit: more context on my end goal.
I am writing a library that helps users create a UDF, which is a dylib with a C interface. The init
, process
, add
, remove
etc. functions map nicely to traits (see my unfinished work here). My goal is that a user of my library can:
- Define a struct or enum (which may be zero-sized, or contain something useful) which will give their UDF name
- Implement my traits on this struct (one trait is required, the second is optional)
- Add a
#[register]
macro to this struct
And from there, my library will generate the correct C interface functions via the macro. This isn't too different from how PyO3 works, I believe.
However, some of the C function signatures depend on the Return
type within BasicUdf
, so my macro needs some way to know what this is. I find it cleaner to put the macro on the main struct, so I am looking for a way to do this (hence this question)
My backup plan is to require placing the macro on the impl
, which isn't terrible but is just less elegent (parsing the Returns
type there is no problem). Something like a PhantomData
marker on the main struct would also work, but I don't find that too ergonomic.