From 5e11aa0abc9684ba6c2883ee691ac50d42c81c9c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Jun 2025 13:59:33 -0700 Subject: [PATCH 01/10] Unwrap cfg attribute --- src/conditional-compilation.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 7440fe0c2..8551e93e3 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -326,22 +326,16 @@ r[cfg.attr.syntax] r[cfg.attr.general] -The `cfg` [attribute] conditionally includes the thing it is attached to based -on a configuration predicate. +The `cfg` [attribute] conditionally includes the thing it is attached to based on a configuration predicate. r[cfg.attr.syntax-explanation] It is written as `cfg`, `(`, a configuration predicate, and finally `)`. r[cfg.attr.effect] -If the predicate is true, the thing is rewritten to not have the `cfg` attribute -on it. If the predicate is false, the thing is removed from the source code. +If the predicate is true, the thing is rewritten to not have the `cfg` attribute on it. If the predicate is false, the thing is removed from the source code. r[cfg.attr.crate-level-attrs] -When a crate-level `cfg` has a false predicate, the behavior is slightly -different: any crate attributes preceding the `cfg` are kept, and any crate -attributes following the `cfg` are removed. This allows `#![no_std]` and -`#![no_core]` crates to avoid linking `std`/`core` even if a `#![cfg(...)]` has -removed the entire crate. +When a crate-level `cfg` has a false predicate, the behavior is slightly different: any crate attributes preceding the `cfg` are kept, and any crate attributes following the `cfg` are removed. This allows `#![no_std]` and `#![no_core]` crates to avoid linking `std`/`core` even if a `#![cfg(...)]` has removed the entire crate. Some examples on functions: From 0de49df757f75dacd26e14706102504ca6550f76 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Jun 2025 14:49:57 -0700 Subject: [PATCH 02/10] Rename cfg.attr.general to intro, and move it to the start This updates to follow the attribute template where the intro should be first. --- src/conditional-compilation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 8551e93e3..79c6ea092 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -318,6 +318,9 @@ Example values: r[cfg.attr] ### The `cfg` attribute +r[cfg.attr.intro] +The `cfg` [attribute] conditionally includes the thing it is attached to based on a configuration predicate. + r[cfg.attr.syntax] ```grammar,configuration @root CfgAttribute -> `cfg` `(` ConfigurationPredicate `)` @@ -325,9 +328,6 @@ r[cfg.attr.syntax] -r[cfg.attr.general] -The `cfg` [attribute] conditionally includes the thing it is attached to based on a configuration predicate. - r[cfg.attr.syntax-explanation] It is written as `cfg`, `(`, a configuration predicate, and finally `)`. From 52b3071452c4c0b5e28d804b77002c14535e8c0f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Jun 2025 14:50:42 -0700 Subject: [PATCH 03/10] Move the cfg example to the intro --- src/conditional-compilation.md | 71 +++++++++++++++++----------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 79c6ea092..ae8c33124 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -321,6 +321,42 @@ r[cfg.attr] r[cfg.attr.intro] The `cfg` [attribute] conditionally includes the thing it is attached to based on a configuration predicate. +> [!EXAMPLE] +> Some examples of using `cfg` on functions: +> +> ```rust +> // The function is only included in the build when compiling for macOS +> #[cfg(target_os = "macos")] +> fn macos_only() { +> // ... +> } +> +> // This function is only included when either foo or bar is defined +> #[cfg(any(foo, bar))] +> fn needs_foo_or_bar() { +> // ... +> } +> +> // This function is only included when compiling for a unixish OS with a 32-bit +> // architecture +> #[cfg(all(unix, target_pointer_width = "32"))] +> fn on_32bit_unix() { +> // ... +> } +> +> // This function is only included when foo is not defined +> #[cfg(not(foo))] +> fn needs_not_foo() { +> // ... +> } +> +> // This function is only included when the panic strategy is set to unwind +> #[cfg(panic = "unwind")] +> fn when_unwinding() { +> // ... +> } +> ``` + r[cfg.attr.syntax] ```grammar,configuration @root CfgAttribute -> `cfg` `(` ConfigurationPredicate `)` @@ -337,41 +373,6 @@ If the predicate is true, the thing is rewritten to not have the `cfg` attribute r[cfg.attr.crate-level-attrs] When a crate-level `cfg` has a false predicate, the behavior is slightly different: any crate attributes preceding the `cfg` are kept, and any crate attributes following the `cfg` are removed. This allows `#![no_std]` and `#![no_core]` crates to avoid linking `std`/`core` even if a `#![cfg(...)]` has removed the entire crate. -Some examples on functions: - -```rust -// The function is only included in the build when compiling for macOS -#[cfg(target_os = "macos")] -fn macos_only() { - // ... -} - -// This function is only included when either foo or bar is defined -#[cfg(any(foo, bar))] -fn needs_foo_or_bar() { - // ... -} - -// This function is only included when compiling for a unixish OS with a 32-bit -// architecture -#[cfg(all(unix, target_pointer_width = "32"))] -fn on_32bit_unix() { - // ... -} - -// This function is only included when foo is not defined -#[cfg(not(foo))] -fn needs_not_foo() { - // ... -} - -// This function is only included when the panic strategy is set to unwind -#[cfg(panic = "unwind")] -fn when_unwinding() { - // ... -} - -``` r[cfg.attr.restriction] The `cfg` attribute is allowed anywhere attributes are allowed. From e0b1eaa4a952d7fbfc7e94a54fa2b5be7b4e6200 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Jun 2025 14:52:04 -0700 Subject: [PATCH 04/10] Remove comment about active cfg It should perhaps say something, but this is already covered in the attributes chapter, and I'm not sure if anything really fits here. --- src/conditional-compilation.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index ae8c33124..e44a2309b 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -362,8 +362,6 @@ r[cfg.attr.syntax] @root CfgAttribute -> `cfg` `(` ConfigurationPredicate `)` ``` - - r[cfg.attr.syntax-explanation] It is written as `cfg`, `(`, a configuration predicate, and finally `)`. From 8d3b6db297b06740818353d088aff9b7eb4cf1e2 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Jun 2025 14:57:50 -0700 Subject: [PATCH 05/10] Remove cfg.attr.syntax-explanation I personally don't think we need to explain the grammar in English. I understand why it could be worthwhile, but I think so many parts of the grammar are so complex that it would be infeasible to describe it all this way. --- src/conditional-compilation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index e44a2309b..dc424ca56 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -358,12 +358,12 @@ The `cfg` [attribute] conditionally includes the thing it is attached to based o > ``` r[cfg.attr.syntax] +The syntax for the `cfg` attribute is: + ```grammar,configuration @root CfgAttribute -> `cfg` `(` ConfigurationPredicate `)` ``` -r[cfg.attr.syntax-explanation] -It is written as `cfg`, `(`, a configuration predicate, and finally `)`. r[cfg.attr.effect] If the predicate is true, the thing is rewritten to not have the `cfg` attribute on it. If the predicate is false, the thing is removed from the source code. From c9a9bcf42a1a5ebdcfd72ecb1297eb5a7f9dc85b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Jun 2025 14:58:08 -0700 Subject: [PATCH 06/10] Rename cfg.attr.restriction --- src/conditional-compilation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index dc424ca56..6962acbfd 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -364,6 +364,8 @@ The syntax for the `cfg` attribute is: @root CfgAttribute -> `cfg` `(` ConfigurationPredicate `)` ``` +r[cfg.attr.allowed-positions] +The `cfg` attribute is allowed anywhere attributes are allowed. r[cfg.attr.effect] If the predicate is true, the thing is rewritten to not have the `cfg` attribute on it. If the predicate is false, the thing is removed from the source code. @@ -372,8 +374,6 @@ r[cfg.attr.crate-level-attrs] When a crate-level `cfg` has a false predicate, the behavior is slightly different: any crate attributes preceding the `cfg` are kept, and any crate attributes following the `cfg` are removed. This allows `#![no_std]` and `#![no_core]` crates to avoid linking `std`/`core` even if a `#![cfg(...)]` has removed the entire crate. -r[cfg.attr.restriction] -The `cfg` attribute is allowed anywhere attributes are allowed. r[cfg.cfg_attr] ### The `cfg_attr` attribute From d92431b097b0e7ccd0a99dd97629a0a2b2209900 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Jun 2025 15:27:54 -0700 Subject: [PATCH 07/10] Add cfg.attr.duplicates --- src/conditional-compilation.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 6962acbfd..f04646721 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -367,14 +367,15 @@ The syntax for the `cfg` attribute is: r[cfg.attr.allowed-positions] The `cfg` attribute is allowed anywhere attributes are allowed. +r[cfg.attr.duplicates] +Multiple `cfg` attributes may be specified. The thing will not be included if any of the `cfg` predicates are false. + r[cfg.attr.effect] If the predicate is true, the thing is rewritten to not have the `cfg` attribute on it. If the predicate is false, the thing is removed from the source code. r[cfg.attr.crate-level-attrs] When a crate-level `cfg` has a false predicate, the behavior is slightly different: any crate attributes preceding the `cfg` are kept, and any crate attributes following the `cfg` are removed. This allows `#![no_std]` and `#![no_core]` crates to avoid linking `std`/`core` even if a `#![cfg(...)]` has removed the entire crate. - - r[cfg.cfg_attr] ### The `cfg_attr` attribute From 2de96a02987cf0b00fff9f99d9bb0feccbde2c36 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Jun 2025 15:28:35 -0700 Subject: [PATCH 08/10] Update cfg.attr.crate-level-attrs This moves the rule to follow the template order, rewords it a bit to simplify, and adds an example to illustrate. Closes https://github.com/rust-lang/reference/issues/103 --- src/conditional-compilation.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index f04646721..644832ff4 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -374,7 +374,21 @@ r[cfg.attr.effect] If the predicate is true, the thing is rewritten to not have the `cfg` attribute on it. If the predicate is false, the thing is removed from the source code. r[cfg.attr.crate-level-attrs] -When a crate-level `cfg` has a false predicate, the behavior is slightly different: any crate attributes preceding the `cfg` are kept, and any crate attributes following the `cfg` are removed. This allows `#![no_std]` and `#![no_core]` crates to avoid linking `std`/`core` even if a `#![cfg(...)]` has removed the entire crate. +When a crate-level `cfg` has a false predicate, the crate itself still exists. Any crate attributes preceding the `cfg` are kept, and any crate attributes following the `cfg` are removed as well as removing all of the following crate contents. + +> [!EXAMPLE] +> The behavior of not removing the preceding attributes allows you to do things such as include `#![no_std]` to avoid linking `std` even if a `#![cfg(...)]` has removed the entire crate. For example: +> +> +> ```rust,ignore +> // This `no_std` attribute is kept even though the crate-level `cfg` +> // attribute is false. +> #![no_std] +> #![cfg(false)] +> +> // This function is not included. +> pub fn example() {} +> ``` r[cfg.cfg_attr] ### The `cfg_attr` attribute From 8e797ea5e84bd763a5bd2054cd4fc6f302942283 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Jun 2025 15:48:20 -0700 Subject: [PATCH 09/10] Add italics to cfg.attr.intro This is to follow the template. --- 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 644832ff4..090ddd755 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -319,7 +319,7 @@ r[cfg.attr] ### The `cfg` attribute r[cfg.attr.intro] -The `cfg` [attribute] conditionally includes the thing it is attached to based on a configuration predicate. +The *`cfg` [attribute]* conditionally includes the thing it is attached to based on a configuration predicate. > [!EXAMPLE] > Some examples of using `cfg` on functions: From cf4e431d6634feb4950e96292ab31d2fe11776af Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 1 Jul 2025 20:46:05 +0000 Subject: [PATCH 10/10] Revise editorially In most of the examples for these attributes, there's no lead-in, so let's remove the lead-in here. Let's also say "form" rather than "thing", even though "thing" does have a certain appeal to it. In our rule for duplicates, let's add a forward reference to the exception to that. Finally, we say that the attribute applied at the crate level does not remove the crate; later, for an example, let's clarify that it only removes the content of the crate. Most or all of this was preexisting to this PR. --- src/conditional-compilation.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 090ddd755..8f24659fe 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -319,11 +319,9 @@ r[cfg.attr] ### The `cfg` attribute r[cfg.attr.intro] -The *`cfg` [attribute]* conditionally includes the thing it is attached to based on a configuration predicate. +The *`cfg` [attribute]* conditionally includes the form to which it is attached based on a configuration predicate. > [!EXAMPLE] -> Some examples of using `cfg` on functions: -> > ```rust > // The function is only included in the build when compiling for macOS > #[cfg(target_os = "macos")] @@ -368,16 +366,16 @@ r[cfg.attr.allowed-positions] The `cfg` attribute is allowed anywhere attributes are allowed. r[cfg.attr.duplicates] -Multiple `cfg` attributes may be specified. The thing will not be included if any of the `cfg` predicates are false. +Multiple `cfg` attributes may be specified. The form to which the attribute is attached will not be included if any of the `cfg` predicates are false except as described in [cfg.attr.crate-level-attrs]. r[cfg.attr.effect] -If the predicate is true, the thing is rewritten to not have the `cfg` attribute on it. If the predicate is false, the thing is removed from the source code. +If the predicate is true, the form is rewritten to not have the `cfg` attribute on it. If the predicate is false, the form is removed from the source code. r[cfg.attr.crate-level-attrs] When a crate-level `cfg` has a false predicate, the crate itself still exists. Any crate attributes preceding the `cfg` are kept, and any crate attributes following the `cfg` are removed as well as removing all of the following crate contents. > [!EXAMPLE] -> The behavior of not removing the preceding attributes allows you to do things such as include `#![no_std]` to avoid linking `std` even if a `#![cfg(...)]` has removed the entire crate. For example: +> The behavior of not removing the preceding attributes allows you to do things such as include `#![no_std]` to avoid linking `std` even if a `#![cfg(...)]` has otherwise removed the contents of the crate. For example: > > > ```rust,ignore