8
votes

I'm using a macro to extend a primitive struct:

pub struct MyTypedNumber(pub u32);
struct_impl_my_features!(MyTypedNumber);

The struct_impl_my_features macro can implement functions & traits for MyTypedNumber, however there is a case where its useful to use #[derive(PartialEq, Eq)] - for example.

Is it possible to use #[derive(...)] after the struct is already declared?

An alternative is to pass in the struct definition as an item argument to a macro:

struct_impl_my_features!(
    pub struct MyTypedNumber(pub u32);,
    MyTypedNumber
);

This works, so it may be the best option, although it is rather clunky and means the declaration and macro extension must be together.

See this complete example, the macro is called struct_bitflag_impl (second example).


I worked around this by manually implementing PartialEq and Eq, however I ran into a case where Rust needs #[derive(...)] to be used as constants within match statement:

= warning: this was previously accepted by the compiler but is being phased out;
  it will become a hard error in a future release!
= note: for more information,
  see RFC 1445 <https://github.com/rust-lang/rfcs/pull/1445>
1
Can you please include a complete example? What has MyTypedNumber got to do with MyTypedInt? - Chris Emerson
MyTypedInt accidentally left in, corrected - added link to complete example. - ideasman42
Derive doesn't do anything magical. You should be able to do the exact same implementation manually that it does. Could you provide the example where you feel you need derive? - paholg
@paholg, thats what I would have expected too and its true in most cases, however the Rust compiler is deprecating support for non-derive equality, see: RFC 1445. - ideasman42

1 Answers

0
votes

The "complete example" link you provide does show an example of having the macro prefix attributes (see the second macro).

    #[derive(PartialEq, Eq, Copy, Clone, Debug)]
    $struct_p_def

However, if instead you want to be able to provide derive-attributes per struct (e.g., only some of your structs need to derive PartialEq), you can pass the derive expression in the first part of your second struct_impl_my_features! example—the attributes are considered part of the item macro form. E.g.,

struct_impl_my_features!(
    #[derive(PartialEq, Eq)]
    pub struct MyTypedNumber(pub u32);,
    MyTypedNumber
);

Update

Sorry, I don't have an answer to your main question; as far as I know, it is not possible. However, if your primary concern is the clunkiness, and if your structs are all of similar form, you could make your macro call nicer by adding this to the top of your macro:

($x:ident ( $($v:tt)* ) ) => {
    struct_impl_my_features!(pub struct $x( $($v)* );, $x)
};

And then calling it like:

struct_impl_my_features!(MyTypedNumber(pub u32));