`cfg_select!` macro by folkertdev · Pull Request #2103 · rust-lang/reference

traviscross

folkertdev

ehuss

ehuss

ehuss

ehuss

@folkertdev @ehuss

@folkertdev @ehuss

Macros can be renamed when imported and can delimit their bodies with
different tokens, so we don't want to document the outer part of the
call; we just want to document the input to the macro.

Doing this for `cfg_select!` is a bit tricky since an expression with
a block doesn't need to be followed by a comma while an expression
without a block does unless it's the last one.  We don't want to
handle this the way that the `match` grammar does, currently, since we
want to move toward finite lookahead.  So, instead, we handle this
with right recursion in `CfgSelectArms`.

Unlike `match`, outer attributes aren't allowed on the RHS
expressions.  To handle this, we need to refactor
`ExpressionWithoutBlock` and `ExpressionWithBlock`.

We also document that the outer braces are removed during expansion
when the payload is a block expression.

(We called it the arm "payload" after running out of other options.)
Co-authored-by: Eric Huss <eric@huss.org>
The rule names for intros should be `.intro`. The intro itself should
not be specifying the behavior. Also, follow the style where there is an
introduction, an example, and then the syntax.

@ehuss

@ehuss

Don't repeat the list of valid macro positions (which is already not
correct here since it is missing some). For the most part, it is assumed
that macro calls can appear in all valid macro invocation positions. If
exceptions are ever added in the future, then they can be called out.

@ehuss

@ehuss

@ehuss

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request

Feb 22, 2026

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request

Feb 22, 2026

jhpratt added a commit to jhpratt/rust that referenced this pull request

Feb 22, 2026

Zalathar added a commit to Zalathar/rust that referenced this pull request

Feb 23, 2026

rust-timer added a commit to rust-lang/rust that referenced this pull request

Feb 23, 2026
Rollup merge of #149783 - folkertdev:stabilize-cfg-select, r=JonathanBrouwer

stabilize `cfg_select!`

*[View all comments](https://triagebot.infra.rust-lang.org/gh-comments/rust-lang/rust/pull/149783)*

tracking issue: #115585
closes #115585
reference PR:

- rust-lang/reference#2103

# 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.

```rust
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:
```rust
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:

- rust-lang/reference#2103

## Tests

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

- [`tests/ui/check-cfg/cfg-select.rs`](https://github.com/rust-lang/rust/blob/main/tests/ui/check-cfg/cfg-select.rs)tests that warnings are emitted when an unexpected `cfg` condition is used.
- [`tests/ui/macros/cfg_select.rs`](https://github.com/rust-lang/rust/blob/main/tests/ui/macros/cfg_select.rs) tests that `cfg_select!` has the expected expansion, and tests that the expected syntax is accepted.
## History

- #115416
- #117162
- #133720
- #135625
- #137198
- #138993
- #138996
- #143461
- #143941
- #145233
- #148712
- #149380
- #149925

# 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

<!-- TRIAGEBOT_START -->

<!-- TRIAGEBOT_CONCERN-ISSUE_START -->

> [!NOTE]
> # Concerns (0 active)
>
> - ~~[allowing-comma-after-closing-brace](#149783 (comment) resolved in [this comment](#149783 (comment))
>
> *Managed by `@rustbot`—see [help](https://forge.rust-lang.org/triagebot/concern.html) for details.*

<!-- TRIAGEBOT_CONCERN-ISSUE_END -->
<!-- TRIAGEBOT_END -->

RalfJung pushed a commit to RalfJung/miri that referenced this pull request

Feb 24, 2026

Merged via the queue into rust-lang:master with commit a5b10fd

Feb 24, 2026

10 of 12 checks passed

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request

Feb 25, 2026

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request

Feb 25, 2026

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request

Feb 25, 2026

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request

Feb 25, 2026

jhpratt added a commit to jhpratt/rust that referenced this pull request

Feb 26, 2026

rust-timer added a commit to rust-lang/rust that referenced this pull request

Feb 26, 2026

RalfJung pushed a commit to RalfJung/miri that referenced this pull request

Feb 26, 2026