Using #[cfg] attributes on types in tuples?

Is there a way to use #[cfg] attributes on tuple members? It looks like it isn't allowed in this position here:

struct Data {
    storage: (u32, i32, #[cfg(feature = "foo")] u8),
}
31 | struct Data {
   |        ---- while parsing this struct
32 |     storage: (u32, i32, #[cfg(feature = "foo")] u8),
   |                         ^ expected type

For large tuples, or tuples generated by macros, it isn't practical to rewrite the entire type multiple times for different cfgs. Is there a workaround? It seems like a good candidate for an RFC similar to 3399-cfg-attribute-in-where.

Use cfg on fields instead.

pub struct Data2 {
    #[cfg(not(feature = "foo"))]
    storage: (u32, i32),
    #[cfg(feature = "foo")] 
    storage: (u32, i32, u8),
}

Large tuples can be replaced with named structs, which is also user-friendly.

pub struct Storage {
    f1: u32,
    f2: i32,
    #[cfg(feature = "foo")]
    f3: u8,
}
pub struct Data {
    storage: Storage,
}

Rust Playground

Thanks, I appreciate the info. Unfortunately neither of those work well for my use case and would add a lot of boilerplate. It isn't practical for me to rewrite very large tuples for multiple different overlapping cfg profiles, and the struct version doesn't work because these need to be tuples for decomposition elsewhere. It's the same problem as in RFC 3399, so I'll probably propose another similar one.

Not sure if I follow - what's wrong with decomposing an ordinary struct?..

Difficult to describe in a forum post, but I'll try. The summary is that I'm using a trick similar to bevy's WorldQuery system (some info here and here) to build quasi-variadic SoA structures. The goal is to be able to declare an ECS archetype as

type MyArchetype = EcsArchetype<(
    ComponentA,
    ComponentB,
    #[cfg(feature = "foo")]
    ComponentC,
)>;

and have it "just work". And it would, if #[cfg] was allowed in this position.

Requiring the user to declare a separate struct and the implementation for it would defeat the purpose of the convenience, since I'm not actually using the tuple for its storage, just for extracting its type information. It would have to be done with macros, and I can't easily use macros because those are evaluated before #[cfg] is, so I'd have to make a whole proc macro system to parse the #[cfg] and that would both complicate the crate structure and hurt compile times, and just be a massive pain.

The funny thing is that it's perfectly fine to use #[cfg] in tuple initialization, just not in tuple type declaration. I wrote that RFC 3399 above to address a similar issue in where clauses, and so I'll probably write something for this as well.

1 Like

Here is that RFC I mentioned, in case anyone is interested or finds this in a search later down the line.

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.