Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use with conditional compilation (cfg-macro)? #56

Closed
DerZade opened this issue Apr 15, 2023 · 6 comments
Closed

How to use with conditional compilation (cfg-macro)? #56

DerZade opened this issue Apr 15, 2023 · 6 comments
Labels
I-support This issue (I) supports the users of the project T-accepted Triage (T): Initial review accepted issue/PR as valid

Comments

@DerZade
Copy link

DerZade commented Apr 15, 2023

I use the duplicate macro to generate a sync and a async version of a function. I would like to include the async version only if the feature async is enabled. Is there any way to achieve that?

The following code, does not work. I guess this is because the cfg macro has a "higher" priority as the duplicate_item macro and therefore it just says "code is inactive due to #[cfg] directives: cfg_filter is disabled"

#[duplicate_item(
    fn_name             cfg_filter        async;
    [my_function]       [all()]           [];
    [my_function_async] [feature="async"] [async];
)]
#[cfg(cfg_filter)]
async fn fn_name() {
    todo!()
}

Thanks a lot in advance!

@DerZade DerZade added the I-support This issue (I) supports the users of the project label Apr 15, 2023
@DerZade DerZade changed the title How to use with cfg How to use with cfg? Apr 15, 2023
@github-actions github-actions bot added the T-new Triage (T): Has yet to be reviewed label Apr 15, 2023
@DerZade DerZade changed the title How to use with cfg? How to use with conditional compilation (cfg-macro)? Apr 15, 2023
@DerZade
Copy link
Author

DerZade commented Apr 15, 2023

After playing around with it a bit more, I found a solution, but it is very verbose:

#[cfg_attr(feature = "async", 
    duplicate_item(
        fn_name             async;
        [my_function]       [];
        [my_function_async] [async];
    )
)]
#[cfg_attr(not(feature = "async"), 
    duplicate_item(
        fn_name             async;
        [my_function]       [];
    )
)]
async fn fn_name() {
    todo!()
}

Is there any better way?

@Emoun Emoun added T-accepted Triage (T): Initial review accepted issue/PR as valid and removed T-new Triage (T): Has yet to be reviewed labels Apr 16, 2023
@Emoun
Copy link
Owner

Emoun commented Apr 16, 2023

I tried your first example, that you said didn't work, and it seems to work for me when using one my feautures (pretty_errors):

With the feature disabled the expansion resulted in:

#[cfg(all())]
fn my_function() {
    ::core::panicking::panic("not yet implemented")
}

With the feature enabled result was:

#[cfg(all())]
fn my_function() {
    ::core::panicking::panic("not yet implemented")
}
#[cfg(feature = "pretty_errors")]
async fn my_function_async() {
    ::core::panicking::panic("not yet implemented")
}

However, I then tried to make another feature called "async", and this didn't work. I also tried a few more names, and they didn't work either. For some reason, only two of my feature names would work. This is extremely weird but also not a problem with duplicate but with #[cfg(feature = "...")] not working for some features.
I confirmed this by testing without using duplicate at all, and seeing that #[cfg(feature = "...")] would always be false for some features but not others.

I don't have time to look into this any more today, but if you can replicate what I've done perhaps this is a bug in the compiler and we should open an issue in rust-lang/rust.

@DerZade
Copy link
Author

DerZade commented Apr 17, 2023

I don't have time to look into this any more today, but if you can replicate what I've done perhaps this is a bug in the compiler and we should open an issue in rust-lang/rust.

The following is my example from the OP with your feature (pretty_errors). Did I understand correctly that that worked for you, because it does not work for me 😅

#[duplicate_item(
    fn_name             cfg_filter                async;
    [my_function]       [all()]                   [];
    [my_function_async] [feature="pretty_errors"] [async];
)]
#[cfg(cfg_filter)]
async fn fn_name() {
    todo!()
}

fn shit() {
    my_function()
}

It does not expand to anything 🤔 and I get the following error

@Emoun
Copy link
Owner

Emoun commented Apr 17, 2023

Trying again, I got the following to work (regardless of feature name, so lets ignore that part of my last comment):

#[duplicate::duplicate_item(
    fn_name             cfg_filter                async;
    [my_function]       [cfg(all())]                   [];
    [my_function_async] [cfg(feature="async")] [async];
)]
#[cfg_filter]
async fn fn_name() {
    todo!()
}

fn shit() {
    my_function()
}

The key was moving cfg( into the substitution for both cases. Let me know if this works for you too.

Having to do this seems to me as a compiler error. If you look at the rust reference, their example shows that attributes should be expanded in descending order, which would imply duplicate should be able do what you originally tried. I'm going to open an issue about this in rustc and we'll see what they say

@Emoun
Copy link
Owner

Emoun commented Apr 17, 2023

@DerZade this issue seems to be known (rust-lang/rust#83331) but will probably not be fixed in the immediate future, so I would stick to moving the cfg( part into duplicate_item as mentioned earlier.

@DerZade
Copy link
Author

DerZade commented Apr 18, 2023

Thank you very much! Moving the cfg( into the duplicate worked flawlessly 🙃

@DerZade DerZade closed this as completed Apr 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I-support This issue (I) supports the users of the project T-accepted Triage (T): Initial review accepted issue/PR as valid
Projects
None yet
Development

No branches or pull requests

2 participants