0

I have an existing macro definition that captures the attributes. Inside that definition, I'm trying to filter and set the attributes selectively.

I have a peculiar problem where I have to set attributes for match arms in one of these cases.

macro_rules! set_mytrait {
    (
        $target:ident
        $(
            $( #[$cfgs:meta] )*
            $field:ident
         ),*
         $(,)*
    ) => {
        impl $crate::MyTrait for $target
        {
            fn perform(&self) -> Option<&(dyn $crate::Error + 'static)> {
                match self { $(
                    // Replace the below attributes with a filter function that returns only some of the attributes 
                    $(#[$cfgs])*
                    $field => {
                        // doSomething($field);
                        None
                    }
                )* }
            }
        }
    }
}

I know that we cannot yet use macros in attributes according to this.

Apart from that, I've tried two options and both seem to have hit roadblocks.

Option 1

Approach: Using macro that takes just attributes as arguments and returns filtered attributes.

Implementation:

piped_attribs

#[macro_export]
macro_rules! piped_attribs {
    (
        $( $attr:tt )*
    ) => {
        // Use filter logic here
        $( #[$attr] )*
    };
}

called_at

match self { $(
    $crate::piped_attribs! { $( $cfgs ),* }
    $field => {
        // doSomething($field)
        None
    }
)* }

Problem: Seems like emitting attributes doesn't work in this context and I require to attach it to an item (source)

Option 2

Approach: Using macro that takes in two args. One for attributes and next for the match arm.

Implementation:

piped_attribs

#[macro_export]
macro_rules! piped_attribs {
    (
        [ $( $attr:tt )* ]
        { $rest: tt }
    ) => {
        // Use filtering logic here
        $( #[$attr] )*
        $rest,
    };
}

called at

match self { $(
    $crate::piped_attribs! {
    [$( $cfgs ),*]
    {$field => {
        // doSomething($field);
        None
    }}
    }
)* }

Problem: I discovered that apparently we cannot return match "arms" from an attribute as of now. issue

Finally... the question

Is any of these approaches feasible and if not, is there a better way to look at this issue?

  • Can you elaborate a bit more on the attributes that you're trying to filter, and more importantly under what circumstances? It sounds like you may be trying to reimplement [`#[cfg_attr(...)]`](https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute) ? – eggyal Apr 11 '21 at 21:07
  • Here is a simple use-case. I want to let any `#[cfg(...)]` pass through but block off `#[doc]` attribute. Moreover, I'd want control (if possible) over which cfg attributes to let through. Ex: `#[cfg(feature = ...)]` should pass but not `#[cfg(target_os = ...)]`. Also I didn't know about `cfg_attr`. I'll have a look and update the comment if that solves something. Also I'd really love it if I could reach a solution that involves calling another macro so that I can modify is more freely. – Utkarsh Bhardwaj Apr 11 '21 at 21:41

0 Answers0