From b4ef15d22c0b7208796548e70ebcac9ac41deafb Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 8 Dec 2025 21:16:20 +0100 Subject: [PATCH 01/11] `cfg_select!` macro --- src/conditional-compilation.md | 37 ++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 5c85ae193a..c39947d690 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -31,7 +31,7 @@ r[cfg.intro] *Conditionally compiled source code* is source code that is compiled only under certain conditions. r[cfg.attributes-macro] -Source code can be made conditionally compiled using the [`cfg`] and [`cfg_attr`] [attributes] and the built-in [`cfg` macro]. +Source code can be made conditionally compiled using the [`cfg`] and [`cfg_attr`] [attributes] and the built-in [`cfg!`] and [`cfg_select!`] [macros]. r[cfg.conditional] Whether to compile can depend on the target architecture of the compiled crate, arbitrary values passed to the compiler, and other things further described below. @@ -436,11 +436,43 @@ let machine_kind = if cfg!(unix) { println!("I'm running on a {} machine!", machine_kind); ``` +r[cfg.cfg_select] +### The `cfg_select` macro + +The built-in `cfg_select` macro expands to the right-hand side of the first configuration predicate that evaluates to `true`. + +For example: + +```rust +cfg_select! { + unix => { + fn foo() { /* unix specific functionality */ } + } + target_pointer_width = "32" => { + fn foo() { /* non-unix, 32-bit functionality */ } + } + _ => { + fn foo() { /* fallback implementation */ } + } +} +``` +The `cfg_select` macro can also be used in expression position: + +```rust +let is_unix_str = cfg_select! { + unix => "unix", + _ => "not unix", +}; +``` + +A `_` can be used to write a configuration predicate that always evaluates to `true`. + [Testing]: attributes/testing.md [`--cfg`]: ../rustc/command-line-arguments.html#--cfg-configure-the-compilation-environment [`--test`]: ../rustc/command-line-arguments.html#--test-build-a-test-harness [`cfg`]: #the-cfg-attribute -[`cfg` macro]: #the-cfg-macro +[`cfg!`]: #the-cfg-macro +[`cfg_select!`]: #the-cfg_select-macro [`cfg_attr`]: #the-cfg_attr-attribute [`crate_name`]: crates-and-source-files.md#the-crate_name-attribute [`crate_type`]: linkage.md @@ -449,4 +481,5 @@ println!("I'm running on a {} machine!", machine_kind); [attributes]: attributes.md [cargo-feature]: ../cargo/reference/features.html [crate type]: linkage.md +[macros]: macros.md [static C runtime]: linkage.md#static-and-dynamic-c-runtimes From 8a3349a7fe3bb385db12ff9fbe88f5552484b0b6 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 17 Dec 2025 17:58:37 +0100 Subject: [PATCH 02/11] more detail --- src/conditional-compilation.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index c39947d690..701dbc5ab0 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -439,7 +439,21 @@ println!("I'm running on a {} machine!", machine_kind); r[cfg.cfg_select] ### The `cfg_select` macro -The built-in `cfg_select` macro expands to the right-hand side of the first configuration predicate that evaluates to `true`. +r[cfg.cfg_select.syntax] +```grammar,configuration +CfgSelect -> + cfg_select! `{` CfgSelectBranch* `}` + +CfgSelectConfigurationPredicate -> + ConfigurationPredicate | `_` + +CfgSelectBranch -> + CfgSelectConfigurationPredicate `=>` `{` TokenTree `}` + | CfgSelectConfigurationPredicate `=>` TokenTree `,` +``` + +r[cfg.cfg_select.general] +The built-in `cfg_select` macro expands to the `TokenTree` on the right-hand side of the first configuration predicate that evaluates to `true`. For example: @@ -465,8 +479,26 @@ let is_unix_str = cfg_select! { }; ``` +r[cfg.cfg_select.wildcard] A `_` can be used to write a configuration predicate that always evaluates to `true`. +r[cfg.cfg_select.fallthrough] +If none of the predicates evaluates to `true`, a compiler error is emitted. + +r[cfg.cfg_select.positions] +The `cfg_select!` macro is accepted in the following macro expansion positions + +- items +- statements +- expression +- impl items +- trait impl items +- trait items +- foreign items + +r[cfg.cfg_select.well-formed] +Each right-hand side must syntactically be valid expansion for the position that the macro is invoked in. + [Testing]: attributes/testing.md [`--cfg`]: ../rustc/command-line-arguments.html#--cfg-configure-the-compilation-environment [`--test`]: ../rustc/command-line-arguments.html#--test-build-a-test-harness From adda47990bbbf1bbdddf00b9561a4b3aecd442d3 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 17 Jan 2026 01:37:26 +0000 Subject: [PATCH 03/11] Add more correct grammar for `cfg_select!` 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.) --- src/conditional-compilation.md | 17 +++++---- src/expressions.md | 66 +++++++++++++++++----------------- 2 files changed, 43 insertions(+), 40 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 701dbc5ab0..50d65825d4 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -441,19 +441,22 @@ r[cfg.cfg_select] r[cfg.cfg_select.syntax] ```grammar,configuration -CfgSelect -> - cfg_select! `{` CfgSelectBranch* `}` +@root CfgSelect -> CfgSelectArms? + +CfgSelectArms -> + CfgSelectConfigurationPredicate `=>` + ( + `{` ^ TokenTree `}` CfgSelectArms? + | ExpressionWithBlockNoAttrs `,`? CfgSelectArms? + | ExpressionWithoutBlockNoAttrs ( `,` CfgSelectArms? )? + ) CfgSelectConfigurationPredicate -> ConfigurationPredicate | `_` - -CfgSelectBranch -> - CfgSelectConfigurationPredicate `=>` `{` TokenTree `}` - | CfgSelectConfigurationPredicate `=>` TokenTree `,` ``` r[cfg.cfg_select.general] -The built-in `cfg_select` macro expands to the `TokenTree` on the right-hand side of the first configuration predicate that evaluates to `true`. +The built-in `cfg_select` macro expands to the arm payload of the first configuration predicate that evaluates to `true`. If the payload is wrapped in curly braces, those are removed during expansion. For example: diff --git a/src/expressions.md b/src/expressions.md index 0cfad80340..2cd563b48d 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -8,41 +8,41 @@ Expression -> | ExpressionWithBlock ExpressionWithoutBlock -> - OuterAttribute* - ( - LiteralExpression - | PathExpression - | OperatorExpression - | GroupedExpression - | ArrayExpression - | AwaitExpression - | IndexExpression - | TupleExpression - | TupleIndexingExpression - | StructExpression - | CallExpression - | MethodCallExpression - | FieldExpression - | ClosureExpression - | AsyncBlockExpression - | ContinueExpression - | BreakExpression - | RangeExpression - | ReturnExpression - | UnderscoreExpression - | MacroInvocation - ) + OuterAttribute* ExpressionWithoutBlockNoAttrs + +ExpressionWithoutBlockNoAttrs -> + LiteralExpression + | PathExpression + | OperatorExpression + | GroupedExpression + | ArrayExpression + | AwaitExpression + | IndexExpression + | TupleExpression + | TupleIndexingExpression + | StructExpression + | CallExpression + | MethodCallExpression + | FieldExpression + | ClosureExpression + | AsyncBlockExpression + | ContinueExpression + | BreakExpression + | RangeExpression + | ReturnExpression + | UnderscoreExpression + | MacroInvocation ExpressionWithBlock -> - OuterAttribute* - ( - BlockExpression - | ConstBlockExpression - | UnsafeBlockExpression - | LoopExpression - | IfExpression - | MatchExpression - ) + OuterAttribute* ExpressionWithBlockNoAttrs + +ExpressionWithBlockNoAttrs -> + BlockExpression + | ConstBlockExpression + | UnsafeBlockExpression + | LoopExpression + | IfExpression + | MatchExpression ``` r[expr.intro] From 4cdb225c1df1470e47bdeb841ba93466a1e29b90 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 17 Feb 2026 20:06:44 +0100 Subject: [PATCH 04/11] Update src/conditional-compilation.md Co-authored-by: Eric Huss --- src/conditional-compilation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 50d65825d4..f2c833e1a6 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -446,7 +446,7 @@ r[cfg.cfg_select.syntax] CfgSelectArms -> CfgSelectConfigurationPredicate `=>` ( - `{` ^ TokenTree `}` CfgSelectArms? + `{` ^ TokenTree `}` `,`? CfgSelectArms? | ExpressionWithBlockNoAttrs `,`? CfgSelectArms? | ExpressionWithoutBlockNoAttrs ( `,` CfgSelectArms? )? ) From e3fb9567d11e4a912f18bb860cf4a6b2af2b1294 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 19 Feb 2026 10:15:59 -0800 Subject: [PATCH 05/11] Rework the cfg_select intro 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. --- src/conditional-compilation.md | 48 ++++++++++++++++------------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index f2c833e1a6..22bdabbab1 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -439,6 +439,29 @@ println!("I'm running on a {} machine!", machine_kind); r[cfg.cfg_select] ### The `cfg_select` macro +r[cfg.cfg_select.intro] +The built-in [`cfg_select!`][std::cfg_select] macro can be used to select code at compile-time based on multiple configuration predicates. + +> [!EXAMPLE] +> ```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", +> }; +> ``` + r[cfg.cfg_select.syntax] ```grammar,configuration @root CfgSelect -> CfgSelectArms? @@ -455,32 +478,7 @@ CfgSelectConfigurationPredicate -> ConfigurationPredicate | `_` ``` -r[cfg.cfg_select.general] -The built-in `cfg_select` macro expands to the arm payload of the first configuration predicate that evaluates to `true`. If the payload is wrapped in curly braces, those are removed during expansion. -For example: - -```rust -cfg_select! { - unix => { - fn foo() { /* unix specific functionality */ } - } - target_pointer_width = "32" => { - fn foo() { /* non-unix, 32-bit functionality */ } - } - _ => { - fn foo() { /* fallback implementation */ } - } -} -``` -The `cfg_select` macro can also be used in expression position: - -```rust -let is_unix_str = cfg_select! { - unix => "unix", - _ => "not unix", -}; -``` r[cfg.cfg_select.wildcard] A `_` can be used to write a configuration predicate that always evaluates to `true`. From 1637914957bc9456fb36eeee48dbc200aabb8333 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 19 Feb 2026 10:16:23 -0800 Subject: [PATCH 06/11] Add specific rules for cfg_select behavior --- src/conditional-compilation.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 22bdabbab1..62a9abfb25 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -478,7 +478,11 @@ CfgSelectConfigurationPredicate -> ConfigurationPredicate | `_` ``` +r[cfg.cfg_select.first-arm] +`cfg_select` expands to the payload of the first arm whose configuration predicate evaluates to true. +r[cfg.cfg_select.braces] +If the entire payload is wrapped in curly braces, the braces are removed during expansion. r[cfg.cfg_select.wildcard] A `_` can be used to write a configuration predicate that always evaluates to `true`. From 6712d5de1d7ca645e18ea4ca5734af7ed5865796 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 19 Feb 2026 10:16:47 -0800 Subject: [PATCH 07/11] Simplify wording of cfg.cfg_select.wildcard --- src/conditional-compilation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 62a9abfb25..e7402079f6 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -485,7 +485,7 @@ r[cfg.cfg_select.braces] If the entire payload is wrapped in curly braces, the braces are removed during expansion. r[cfg.cfg_select.wildcard] -A `_` can be used to write a configuration predicate that always evaluates to `true`. +The configuration predicate `_` always evaluates to true. r[cfg.cfg_select.fallthrough] If none of the predicates evaluates to `true`, a compiler error is emitted. From 032f9abc1acecae716b2bbd4a5e13a0879909739 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 19 Feb 2026 10:19:05 -0800 Subject: [PATCH 08/11] Remove cfg.cfg_select.positions 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. --- src/conditional-compilation.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index e7402079f6..3bf0bea4c0 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -490,17 +490,6 @@ The configuration predicate `_` always evaluates to true. r[cfg.cfg_select.fallthrough] If none of the predicates evaluates to `true`, a compiler error is emitted. -r[cfg.cfg_select.positions] -The `cfg_select!` macro is accepted in the following macro expansion positions - -- items -- statements -- expression -- impl items -- trait impl items -- trait items -- foreign items - r[cfg.cfg_select.well-formed] Each right-hand side must syntactically be valid expansion for the position that the macro is invoked in. From a824e615596554ffd7bf1a71c8715e479edcd647 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 19 Feb 2026 10:19:27 -0800 Subject: [PATCH 09/11] Simplify wording of cfg.cfg_select.fallthrough --- src/conditional-compilation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 3bf0bea4c0..54c5269965 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -488,7 +488,7 @@ r[cfg.cfg_select.wildcard] The configuration predicate `_` always evaluates to true. r[cfg.cfg_select.fallthrough] -If none of the predicates evaluates to `true`, a compiler error is emitted. +It is a compile error if none of the predicates evaluate to true. r[cfg.cfg_select.well-formed] Each right-hand side must syntactically be valid expansion for the position that the macro is invoked in. From 11e5d04958177430ef90439dd2b76dabdd24dd6f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 19 Feb 2026 10:19:57 -0800 Subject: [PATCH 10/11] Improve wording of cfg.cfg_select.well-formed --- src/conditional-compilation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 54c5269965..4252af0fdb 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -491,7 +491,7 @@ r[cfg.cfg_select.fallthrough] It is a compile error if none of the predicates evaluate to true. r[cfg.cfg_select.well-formed] -Each right-hand side must syntactically be valid expansion for the position that the macro is invoked in. +Each right-hand side must be a syntactically valid expansion for the position in which the macro is invoked. [Testing]: attributes/testing.md [`--cfg`]: ../rustc/command-line-arguments.html#--cfg-configure-the-compilation-environment From 5c1d0c5a9b616348d036f780d806ede5ecbd4f3c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 19 Feb 2026 10:20:40 -0800 Subject: [PATCH 11/11] Fix sorting of cfg_select! link definition --- src/conditional-compilation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 4252af0fdb..c0351610d6 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -498,8 +498,8 @@ Each right-hand side must be a syntactically valid expansion for the position in [`--test`]: ../rustc/command-line-arguments.html#--test-build-a-test-harness [`cfg`]: #the-cfg-attribute [`cfg!`]: #the-cfg-macro -[`cfg_select!`]: #the-cfg_select-macro [`cfg_attr`]: #the-cfg_attr-attribute +[`cfg_select!`]: #the-cfg_select-macro [`crate_name`]: crates-and-source-files.md#the-crate_name-attribute [`crate_type`]: linkage.md [`target_feature` attribute]: attributes/codegen.md#the-target_feature-attribute