Skip to content

Conversation

@folkertdev
Copy link
Contributor

@folkertdev folkertdev commented Dec 8, 2025

tracking issue: #115585
closes #115585
reference PR:

Request for Stabilization

Summary

The cfg_select! macro picks the expansion corresponding to the first cfg condition that evaluates to true. It simplifies complex conditional expressions.

cfg_select! {
    unix => {
        fn foo() { /* unix specific functionality */ }
    }
    target_pointer_width = "32" => {
        fn foo() { /* non-unix, 32-bit functionality */ }
    }
    _ => {
        fn foo() { /* fallback implementation */ }
    }
}

let is_unix_str = cfg_select! {
    unix => "unix",
    _ => "not unix",
};
println!("{is_unix_str}");

Semantics

The expansion of a cfg_select! call is the right-hand side of the first cfg rule that evaluates to true.

This can be roughly expressed using this macro:

macro_rules! cfg_select {
    ({ $($tt:tt)* }) => {{
        $crate::cfg_select! { $($tt)* }
    }};
    (_ => { $($output:tt)* }) => {
        $($output)*
    };
    (
        $cfg:meta => $output:tt
        $($( $rest:tt )+)?
    ) => {
        #[cfg($cfg)]
        $crate::cfg_select! { _ => $output }
        $(
            #[cfg(not($cfg))]
            $crate::cfg_select! { $($rest)+ }
        )?
    }
}

The actual implementation uses a builtin macro so that cfg_select! can be used both in item and expression position.

Documentation

reference PR:

Tests

The cfg_select! macro is already used extensively in the rust compiler codebase. It has several dedicated tests:

History

Resolved questions

Unresolved questions

The style team has decided on how to format cfg_select!, but this formatting has not yet been implemented. See #144323.

r? @traviscross

@rustbot rustbot added A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 8, 2025
@folkertdev folkertdev added the F-cfg_select `#![feature(cfg_select)]` label Dec 8, 2025
@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the stabilize-cfg-select branch from c4d3570 to 0e24d24 Compare December 8, 2025 19:49
@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the stabilize-cfg-select branch from 0e24d24 to c87e26a Compare December 8, 2025 20:25
@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the stabilize-cfg-select branch from c87e26a to 67d1d43 Compare December 8, 2025 21:07
@ehuss
Copy link
Contributor

ehuss commented Dec 8, 2025

Happy to see this move forward!

Is there a detailed description of how this macro works? For example:

  • What is the grammar that it accepts?
  • How does it expand? For example, it seems like if the RHS uses braces, the braces are implicitly removed.
  • Am I correct that whether or not this fails to compile depends on the current cfg's for the current target/environment? That is, there is essentially an implicit _ => {compile_error!()} as the last rule?
  • Is it correct that this did not suffer the same fate as assert_matches because the name cfg_select is not in use by any known libraries? (Just curious, cfg_select has already been in the prelude for a while and nobody complained.)
  • Is there a reason the unreachable predicate warning isn't a lint? (The main reason I ask is because this prevents -D warnings from catching it.)
  • Am I correct that the RHS is not parsed unless it is the arm that is selected? That is, the right hand side can contain any token tree?

@folkertdev folkertdev marked this pull request as ready for review December 8, 2025 23:06
@rustbot
Copy link
Collaborator

rustbot commented Dec 8, 2025

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

The Miri subtree was changed

cc @rust-lang/miri

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 8, 2025
@folkertdev folkertdev added the I-lang-nominated Nominated for discussion during a lang team meeting. label Dec 8, 2025
@folkertdev
Copy link
Contributor Author

Is there a detailed description of how this macro works? For example:

Not yet, I think.

What is the grammar that it accepts?

In item positions the body should consist of zero or more

('_' | ConfugurationPredicate) => { TokenTree }

In expression position we additionally accept

('_' | ConfugurationPredicate) => Expr,

How does it expand? For example, it seems like if the RHS uses braces, the braces are implicitly removed.

That is correct, one level of braces is removed if braces are used.

Am I correct that whether or not this fails to compile depends on the current cfg's for the current target/environment? That is, there is essentially an implicit _ => {compile_error!()} as the last rule?

Yes if none of the conditions evaluate to true you'll get a compile error (note: earlier iterations did not have this default behavior)

Is it correct that this did not suffer the same fate as assert_matches because the name cfg_select is not in use by any known libraries? (Just curious, cfg_select has already been in the prelude for a while and nobody complained.)

The ecosystem mostly uses cfg_if. But I'll defer to T-libs-api on whether this is exported from all the right places.

Is there a reason the unreachable predicate warning isn't a lint? (The main reason I ask is because this prevents -D warnings from catching it.)

I don't think there is a reason. We could make it a lint (or add it to an existing one?)

Am I correct that the RHS is not parsed unless it is the arm that is selected? That is, the right hand side can contain any token tree?

Yes, the rhs can be any token tree.

@traviscross traviscross added T-lang Relevant to the language team T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang labels Dec 8, 2025
@traviscross
Copy link
Contributor

Is there a reason the unreachable predicate warning isn't a lint? (The main reason I ask is because this prevents -D warnings from catching it.)

I don't think there is a reason. We could make it a lint (or add it to an existing one?)

For my part, it seems worth doing this. Then we can stabilize this lint along with this FCP. Perhaps a new lint named unreachable_cfgs would be correct. The name is by analogy to unexpected_cfgs and unreachable_patterns.

(In the alternate, if we did want "predicate" in the name, I'd suggest unreachable_cfg_predicates.)

@traviscross traviscross added the needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. label Dec 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-run-make Area: port run-make Makefiles to rmake.rs F-cfg_select `#![feature(cfg_select)]` I-lang-nominated Nominated for discussion during a lang team meeting. needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team T-libs Relevant to the library team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tracking issue for cfg_select (formerly cfg_match)

6 participants