Replacement for a custom deriving-like attribute


#1

The glium library is currently providing a plugin named glium_macros which contains two custom attributes: #[vertex_format] and #[uniforms]. As part of 1.0 stabilization, I’m attempting to provide alternatives to these attributes. #[uniforms] was easy to replace, but #[vertex_format] is giving me troubles.

The #[vertex_format] attribute is not complicated: it is simply a custom deriving-like attribute. You can see it in action here:

#[vertex_format]
#[derive(Copy)]
struct Vertex {
    position: [f32; 2],
    color: [f32; 3],
}

This attribute derives the Vertex trait by reading the layout of the struct.

But how do I write a regular macro (with macro_rules!) as an alternative to this?

I tried writing something like this:

macro_rules! attributes {
    ($(#[$attr:meta])* struct $struct_name:ident {
        $($(#[$field_attr:meta])* $field:ident: $t:ty),*
    }) => {
        #[derive(Copy)]
        $(#[$attr])*
        pub struct $struct_name {
            $(
                $($field_attr)* pub $field: $t
            ),+
        }

        impl $crate::vertex::Vertex for $struct_name {
            ...
        }
    }
}

However it can’t be used from within functions, or I get the following error:

:13:9: 13:13 error: macro expansion ignores token impl and any following
:13 impl $crate::vertex::Vertex for $struct_name {

I tried various tricks with modules/use/etc. but I can’t make anything work.

You might say “just let the users derive it themselves”. But the Vertex trait is unsafe and implementing it is error-prone. You might also say “just add a macro that implements the trait, and separate it from the struct declaration”, but that would require writing the struct declaration twice.

Is there a way to solve this properly?


#2

cc @erickt (20chars)