Skip to content

Commit be11d8e

Browse files
committed
Make check-cfg docs more user-friendly
1 parent a61b14d commit be11d8e

File tree

2 files changed

+99
-61
lines changed

2 files changed

+99
-61
lines changed

src/doc/rustc/src/check-cfg.md

Lines changed: 91 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,51 @@
11
# Checking conditional configurations
22

3-
`rustc` accepts the `--check-cfg` option, which specifies whether to check conditions and how to
4-
check them. The `--check-cfg` option takes a value, called the _check cfg specification_.
5-
This specification has one form:
3+
`rustc` supports checking that every _reachable_[^reachable] `#[cfg]` matches a list of the
4+
expected config names and values.
65

7-
1. `--check-cfg cfg(...)` mark a configuration and it's expected values as expected.
6+
This can help with verifying that the crate is correctly handling conditional compilation for
7+
different target platforms or features. It ensures that the cfg settings are consistent between
8+
what is intended and what is used, helping to catch potential bugs or errors early in the
9+
development process.
810

9-
*No implicit expectation is added when using `--cfg`. Users are expected to
10-
pass all expected names and values using the _check cfg specification_.*
11+
In order to accomplish that goal, `rustc` accepts the `--check-cfg` flag, which specifies
12+
whether to check conditions and how to check them.
1113

12-
## The `cfg(...)` form
14+
> **Note:** No implicit expectation is added when using `--cfg`. Users are expected to
15+
pass all expected names and values using the _check cfg specification_.
1316

14-
The `cfg(...)` form enables checking the values within list-valued conditions. It has this
15-
basic form:
17+
[^reachable]: `rustc` promises to at least check reachable `#[cfg]`, and while non-reachable
18+
`#[cfg]` are not currently checked, they may well be checked in the future without it being a
19+
breaking change.
20+
21+
## Specifying and configuring expected names and values
22+
23+
To specify and configuring expected names and values, the _check cfg specification_ provides
24+
the `cfg(...)` option which enables specifying for an expected config name and it's expected
25+
values.
26+
27+
It has this basic form:
1628

1729
```bash
1830
rustc --check-cfg 'cfg(name, values("value1", "value2", ... "valueN"))'
1931
```
2032

2133
where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal
2234
string. `name` specifies the name of the condition, such as `feature` or `my_cfg`.
35+
`"value"` specify one of the value of that condition name.
36+
37+
When the `cfg(...)` option is specified, `rustc` will check every[^reachable]:
38+
- `#[cfg(name = "value")]` attribute
39+
- `#[cfg_attr(name = "value")]` attribute
40+
- `#[link(name = "a", cfg(name = "value"))]` attribute
41+
- `cfg!(name = "value")` macro call
2342

24-
When the `cfg(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]`
25-
attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]`
26-
attribute and `cfg!(name = "value")` macro call. It will check that the `"value"` specified is
27-
present in the list of expected values. If `"value"` is not in it, then `rustc` will report an
28-
`unexpected_cfgs` lint diagnostic. The default diagnostic level for this lint is `Warn`.
43+
> *The command line `--cfg` arguments are currently *NOT* checked but may very well be checked
44+
in the future.*
2945

30-
*The command line `--cfg` arguments are currently *NOT* checked but may very well be checked in
31-
the future.*
46+
`rustc` will check that the `"value"` specified is present in the list of expected values.
47+
If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs` lint diagnostic.
48+
The default diagnostic level for this lint is `Warn`.
3249

3350
To check for the _none_ value (ie `#[cfg(foo)]`) one can use the `none()` predicate inside
3451
`values()`: `values(none())`. It can be followed or preceded by any number of `"value"`.
@@ -43,12 +60,12 @@ rustc --check-cfg 'cfg(name, values(none()))'
4360

4461
To enable checking of name but not values, use one of these forms:
4562

46-
- No expected values (_will lint on every value_):
63+
- No expected values (_will lint on every value of `name`_):
4764
```bash
4865
rustc --check-cfg 'cfg(name, values())'
4966
```
5067

51-
- Unknown expected values (_will never lint_):
68+
- Unknown expected values (_will never lint on value of `name`_):
5269
```bash
5370
rustc --check-cfg 'cfg(name, values(any()))'
5471
```
@@ -59,16 +76,27 @@ To avoid repeating the same set of values, use this form:
5976
rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'
6077
```
6178

79+
To enable checking without specifying any names or values, use this form:
80+
81+
```bash
82+
rustc --check-cfg 'cfg()'
83+
```
84+
6285
The `--check-cfg cfg(...)` option can be repeated, both for the same condition name and for
6386
different names. If it is repeated for the same condition name, then the sets of values for that
6487
condition are merged together (precedence is given to `values(any())`).
6588
89+
> To help out an equivalence table between `--cfg` arguments and `--check-cfg` is available
90+
[down below](#equivalence-table-with---cfg).
91+
6692
## Well known names and values
6793
68-
`rustc` has a internal list of well known names and their corresponding values.
69-
Those well known names and values follows the same stability as what they refer to.
94+
In order to avoid the need for users have to specify configs set by Rust Toolchain, `rustc`
95+
maintains a list of well known names and their corresponding values.
96+
97+
> Those well known names and values follows the same stability as what they refer to.
7098
71-
Well known names and values checking is always enabled as long as at least one
99+
Well known names and values are implicitly added as long as at least one
72100
`--check-cfg` argument is present.
73101
74102
As of `2024-04-06T`, the list of known names is as follows:
@@ -108,11 +136,9 @@ As of `2024-04-06T`, the list of known names is as follows:
108136
Like with `values(any())`, well known names checking can be disabled by passing `cfg(any())`
109137
as argument to `--check-cfg`.
110138
111-
## Examples
112-
113-
### Equivalence table
139+
## Equivalence table with `--cfg`
114140
115-
This table describe the equivalence of a `--cfg` argument to a `--check-cfg` argument.
141+
This table describe the equivalence between a `--cfg` argument to a `--check-cfg` argument.
116142
117143
| `--cfg` | `--check-cfg` |
118144
|-------------------------------|------------------------------------------------------------|
@@ -124,40 +150,42 @@ This table describe the equivalence of a `--cfg` argument to a `--check-cfg` arg
124150
| `--cfg foo="1" --cfg bar="2"` | `--check-cfg=cfg(foo, values("1")) --check-cfg=cfg(bar, values("2"))` |
125151
| `--cfg foo --cfg foo="bar"` | `--check-cfg=cfg(foo, values(none(), "bar"))` |
126152
153+
## Examples
154+
127155
### Example: Cargo-like `feature` example
128156
129157
Consider this command line:
130158
131159
```bash
132160
rustc --check-cfg 'cfg(feature, values("lion", "zebra"))' \
133-
--cfg 'feature="lion"' -Z unstable-options example.rs
161+
--cfg 'feature="lion"' example.rs
134162
```
135163
136-
This command line indicates that this crate has two features: `lion` and `zebra`. The `lion`
164+
> This command line indicates that this crate has two features: `lion` and `zebra`. The `lion`
137165
feature is enabled, while the `zebra` feature is disabled.
138-
Given the `--check-cfg` arguments, exhaustive checking of names and
139-
values are enabled.
140166
141-
`example.rs`:
142167
```rust
143-
#[cfg(feature = "lion")] // This condition is expected, as "lion" is an expected value of `feature`
168+
#[cfg(feature = "lion")] // This condition is expected, as "lion" is an
169+
// expected value of `feature`
144170
fn tame_lion(lion: Lion) {}
145171
146-
#[cfg(feature = "zebra")] // This condition is expected, as "zebra" is an expected value of `feature`
147-
// but the condition will still evaluate to false
148-
// since only --cfg feature="lion" was passed
172+
#[cfg(feature = "zebra")] // This condition is expected, as "zebra" is an expected
173+
// value of `feature` but the condition will evaluate
174+
// to false since only --cfg feature="lion" was passed
149175
fn ride_zebra(z: Zebra) {}
150176
151-
#[cfg(feature = "platypus")] // This condition is UNEXPECTED, as "platypus" is NOT an expected value of
152-
// `feature` and will cause a compiler warning (by default).
177+
#[cfg(feature = "platypus")] // This condition is UNEXPECTED, as "platypus" is NOT
178+
// an expected value of `feature` and will cause a
179+
// the compiler to emit the `unexpected_cfgs` lint
153180
fn poke_platypus() {}
154181
155-
#[cfg(feechure = "lion")] // This condition is UNEXPECTED, as 'feechure' is NOT a expected condition
156-
// name, no `cfg(feechure, ...)` was passed in `--check-cfg`
182+
#[cfg(feechure = "lion")] // This condition is UNEXPECTED, as 'feechure' is NOT
183+
// a expected condition name, no `cfg(feechure, ...)`
184+
// was passed in `--check-cfg`
157185
fn tame_lion() {}
158186
159-
#[cfg(windows = "unix")] // This condition is UNEXPECTED, as while 'windows' is a well known
160-
// condition name, it doesn't expect any values
187+
#[cfg(windows = "unix")] // This condition is UNEXPECTED, as the well known
188+
// 'windows' cfg doesn't expect any values
161189
fn tame_windows() {}
162190
```
163191
@@ -166,50 +194,54 @@ fn tame_windows() {}
166194
```bash
167195
rustc --check-cfg 'cfg(is_embedded, has_feathers)' \
168196
--check-cfg 'cfg(feature, values("zapping", "lasers"))' \
169-
--cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options
197+
--cfg has_feathers --cfg 'feature="zapping"'
170198
```
171199
172200
```rust
173-
#[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was provided in --check-cfg
174-
fn do_embedded() {} // and doesn't take any value
201+
#[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was
202+
// provided in --check-cfg and doesn't take any value
203+
fn do_embedded() {}
175204
176-
#[cfg(has_feathers)] // This condition is expected, as 'has_feathers' was provided in --check-cfg
177-
fn do_features() {} // and doesn't take any value
205+
#[cfg(has_feathers)] // This condition is expected, as 'has_feathers' was
206+
// provided in --check-cfg and doesn't take any value
207+
fn do_features() {}
178208
179-
#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz' was NEVER provided
180-
// in any --check-cfg arguments
209+
#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz'
210+
// was NEVER provided in any --check-cfg arguments
181211
fn do_mumble_frotz() {}
182212
183-
#[cfg(feature = "lasers")] // This condition is expected, as "lasers" is an expected value of `feature`
213+
#[cfg(feature = "lasers")] // This condition is expected, as "lasers" is an
214+
// expected value of `feature`
184215
fn shoot_lasers() {}
185216
186-
#[cfg(feature = "monkeys")] // This condition is UNEXPECTED, as "monkeys" is NOT an expected value of
187-
// `feature`
217+
#[cfg(feature = "monkeys")] // This condition is UNEXPECTED, as "monkeys" is NOT
218+
// an expected value of `feature`
188219
fn write_shakespeare() {}
189220
```
190221
191222
### Example: Condition names without values
192223
193224
```bash
194225
rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \
195-
--cfg has_feathers -Z unstable-options
226+
--cfg has_feathers
196227
```
197228
198229
```rust
199-
#[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was provided in --check-cfg
200-
// as condition name
230+
#[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was
231+
// provided in --check-cfg as condition name
201232
fn do_embedded() {}
202233
203-
#[cfg(has_feathers)] // This condition is expected, as "has_feathers" was provided in --check-cfg
204-
// as condition name
234+
#[cfg(has_feathers)] // This condition is expected, as "has_feathers" was
235+
// provided in --check-cfg as condition name
205236
fn do_features() {}
206237
207-
#[cfg(has_feathers = "zapping")] // This condition is expected, as "has_feathers" was provided in
208-
// and because *any* values is expected for 'has_feathers' no
238+
#[cfg(has_feathers = "zapping")] // This condition is expected, as "has_feathers"
239+
// was provided and because *any* values is
240+
// expected for 'has_feathers' no
209241
// warning is emitted for the value "zapping"
210242
fn do_zapping() {}
211243
212-
#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz' was not provided
213-
// in any --check-cfg arguments
244+
#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz'
245+
// was not provided in any --check-cfg arguments
214246
fn do_mumble_frotz() {}
215247
```

src/doc/rustc/src/command-line-arguments.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,15 @@ For examples, `--cfg 'verbose'` or `--cfg 'feature="serde"'`. These correspond
1919
to `#[cfg(verbose)]` and `#[cfg(feature = "serde")]` respectively.
2020

2121
<a id="option-check-cfg"></a>
22-
## `--check-cfg`: enables checking conditional configurations
22+
## `--check-cfg`: configure compile-time checking of conditional compilation
23+
24+
This flag enables checking conditional configurations of the crate at compile-time,
25+
specifically it helps configure the set of expected cfg names and values, in order
26+
to check that every _reachable_ `#[cfg]` matches the expected config names and values.
27+
28+
This is different from the `--cfg` flag above which activates some config but do
29+
not expect them. This is useful to prevent stalled conditions, typos, ...
2330

24-
This flag will enable checking conditional configurations.
2531
Refer to the [Checking conditional configurations](check-cfg.md) of this book
2632
for further details and explanation.
2733

0 commit comments

Comments
 (0)