Conditional compilation on field with proc-macro on struct

Hi,
I'm trying to have conditional compilation while using a complex proc-macro here is an example.
When a field is behind a feature, the compilation fails since the field cannot be found.

#[complex_macro] // This macro changes puts the fields private and creates getters and setters
pub struct SomeStruct {
    pub always_enabled: AlwaysEnabled,

    // The complex-macro creates a private field with get/set, but compilation fails if not enabled since field does not exist.
    #[cfg(feature = "some-feature")] 
    pub feature_only: FeatureOnly,
}

I am getting struct SomeStruct has no field 'feature_only'and no field feature_only on type SomeStruct. Is there anyway to circumvent this?

Your macro will be able to see the cfg attribute on the field, and it should copy that attribute to the getter and setter it creates, so that they can be conditional in the same way.

To illustrate:

for field in ...fields {
    let cfgs =
        field
            .attrs
            .iter()
            .filter(|a| a.path.is_ident(cfg))
            .collect::<Vec<_>>() // could be skipped if using `cfgs` in quote only once
    ;
    // ...
    quote!(
        // ...
        #(#cfgs)*
        pub fn getter...

Also, on nightly there is #[cfg_eval], which users can feed to the struct before your own attribute:

#[cfg_eval]
#[complex_macro]
// ...

Finally, derive macros have a magical cfg_eval functionality bundled into them, so you could also do the following hacky approach:

#[complex_macro]
...

to emit:

#[derive(GettersAndSetters)]
/* input but with fields made private */

That way the getter and setter more complex logic won't have to deal with cfgs :person_shrugging:

3 Likes

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.