duplicate
duplicate copied to clipboard
allow cfg attributes on substitution groups
Short Description:
Allows the use of cfg attributes on substitution groups, such that they can be enabled and disabled at build time.
Motivation:
See this code.
Here, they use two cfg_attrs to remove one substitution group based on whether a specific feature is enabled.
This is a bit ugly, as the two invocations of duplicate are identical except for the second substitution group not being present on the second invocation.
Therefore, the first substitution group is actually copied between the two invocations.
It would be better to be able to, within the invocation itself, be able to disable a substitution group using a method akin to cfg_attr.
Design
This could be one way of designing it (this is using verbose syntax to match that of the above example):
duplicate_item(
[
module_type [non_blocking]
maybe_async_attr [maybe_async::must_be_async]
File [tokio::fs::File]
HttpBody [reqwest::Body]
HttpClient [reqwest::Client]
]
#[cfg_attr(feature = "non_blocking")]
[
module_type [blocking]
maybe_async_attr [maybe_async::must_be_sync]
File [std::fs::File]
HttpBody [reqwest::blocking::Body]
HttpClient [reqwest::blocking::Client]
]
))]
This will disable the second substitution group when the non_blocking feature is disabled, exactly like the current semantics of the above example.
This would work the same way for the short syntax and global substitutions (where each attribute would work on just one substitution group or substitution).
Misc:
Open questions:
- [ ] Could this be implemented by calling
cfg_attrdirectly fromduplicate, such that it can return an empty string when thecfgis false? - [ ] Can this be extended to any attribute macro and not just
cfgorcfg_attr?
Could this be implemented by calling cfg_attr directly from duplicate, such that it can return an empty string when the cfg is false?
There is no official stable API to evaluate the cfg attributes or just get the results of their predicates.
I did some hacks in my proc-macro crate for generating builders to essentially get the results of cfg predicates evaluation that I described in a discussion here: ~~https://github.com/elastio/bon/discussions/124. There was also suggested an alternative approach with a derive on some of the generated items, but it also has its drawbacks.~~
UPD: ignore that discussion, because it has too little context. See my message below
I just noticed how much context that discussion lacks. I recommend you to just take a look at this code comment/macro here instead.
The idea is that when the proc macro detects any usage of cfg/cfg_attr attributes it generates a transitively-recursive call to the macro_rules (I posted a link to it). Then macro_rules generate use items that dispatch to true/false variants of macro_rules and then they collect the results of all cfg predicates evaluations into a list and call back to the original proc macro with #[macro_name(___cfgs(results) ...)] prepended in the argument list
@Veetaha thank you for your explanations and links. It good to know that there probably is a workable implementation, though I would need to sit down and focus to really get my head around how it works.