How to pass multiple items to a Derive macro?

How can I create a Derive macro that sees multiple items as its input? The short answer of course is that I can't. But I'm open to any clever workarounds.

Background: A perennial complaint about Mockall is that #[automock] doesn't work on structs that implement multiple traits. The reason is because implementing multiple traits inherently requires using multiple items. I'd really like to fix this. Also, I'd like to switch to a Derive macro instead of an Attribute macro so I can have helper attributes, but that's not 100% necessary.

Ideal Solution: What I really want is to do something like this. But it doesn't work because you can't arbitrarily group items into braces.

trait A {}
trait B {}
#[derive(Mock)]
{
    pub struct MultiTrait {}
    impl A for MultiTrait {}
    impl B for MultiTrait {}
}

Hack 1: One hack would be to group the items in a module. But that's annoying, because the user will have to add some use statements:

trait A {}
trait B {}
#[derive(Mock)]
mod annoying {
    pub struct MultiTrait {}
    impl A for MultiTrait {}
    impl B for MultiTrait {}
}
use annoying::Multitrait;

Hack 2: Another hack would be to redefine the traits inside of helper attributes. That would work and it would have less impact when mocking is disabled (for example in non-test mode), but it would require duplicating a lot of code. Worse, editors won't apply correct syntax highlighting to the trait definitions:

#[cfg_attr(test, derive(Mock))]
#[cfg_attr(test, impl A for MultiTrait {})]
#[cfg_attr(test, impl B for MultiTrait {})]
struct MultiTrait {}

Hack 3: A third hack would be to use a function-like macro. But that precludes the use of helper attributes, can't be disabled in non-test mode, and (like the first hack) adds extra indentation:

multimock! {
    pub struct MultiTrait {}
    impl A for MultiTrait {}
    impl B for MultiTrait {}
}

Hack 4: The wildest idea I have is to have an "open-ended" derive macro. When its input is decorated with a special helper attribute, it won't emit real code. Instead, it will emit some giant helper macro that will be consumed by the following derive macro. In that way, I could pass information from one derive macro invocation to another. But it's also pretty ugly, and it might not work since the information-passing attribute will end up above the succeeding derive attribute:

#[derive(Mock)]
#[has_more_impls]
struct MultiTrait {}
#[derive(Mock)]
#[has_more_impls]
impl A for MultiTrait {}
impl B for MultiTrait {}

Plea: Is there a better way? Surely I'm not the first person to be frustrated by this limitation.

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.