0

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:

  1. Define a struct or enum (which may be zero-sized, or contain something useful) which will give their UDF name
  2. Implement my traits on this struct (one trait is required, the second is optional)
  3. 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.

Trevor Gross
  • 454
  • 3
  • 11
  • Quick thought: maybe my task is possible without proc macros to create a trait that specifies a function signature and implement it on acceptable types. Or, the same sort of thing but return a token stream that could be processed by the macro. Or, maybe something with `chalk` which I don't know much about. Much to test... – Trevor Gross Sep 29 '22 at 20:54
  • You can't access tokens outside the macros. Maybe if you'll expand on your actual use case we'll be able to help. – Chayim Friedman Sep 29 '22 at 21:07
  • I know that any tokens outside the macro aren't visible, but I am hoping there is a pattern that I can add that allows for this and I am simply not aware of. Along the lines of the `quote_spanned` example of adding a struct with a `where` clause, that never would have occured to me. I added more context about the end goal, macro location is really just an ergonomics thing here – Trevor Gross Sep 29 '22 at 22:01

0 Answers0