Skip to content

Commit a556a2a

Browse files
committed
Add compiler flag --check-cfg to the unstable book
1 parent 8d3de56 commit a556a2a

File tree

1 file changed

+221
-0
lines changed

1 file changed

+221
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# `check-cfg`
2+
3+
The tracking issue for this feature is: [#82450](https://github.com/rust-lang/rust/issues/82450).
4+
5+
------------------------
6+
7+
This feature allows you to enable complete or partial checking of configuration.
8+
9+
`rustc` accepts the `--check-cfg` option, which specifies whether to check conditions and how to
10+
check them. The `--check-cfg` option takes a value, called the _check cfg specification_. The
11+
check cfg specification is parsed using the Rust metadata syntax, just as the `--cfg` option is.
12+
13+
`--check-cfg` option can take one of two forms:
14+
15+
1. `--check-cfg names(...)` enables checking condition names.
16+
2. `--check-cfg values(...)` enables checking the values within list-valued conditions.
17+
18+
These two options are independent. `names` checks only the namespace of condition names
19+
while `values` checks only the namespace of the values of list-valued conditions.
20+
21+
## The `names(...)` form
22+
23+
The `names(...)` form enables checking the names. This form uses a named list:
24+
25+
```bash
26+
rustc --check-cfg 'names(name1, name2, ... nameN)'
27+
```
28+
29+
where each `name` is a bare identifier (has no quotes). The order of the names is not significant.
30+
31+
If `--check-cfg names(...)` is specified at least once, then `rustc` will check all references to
32+
condition names. `rustc` will check every `#[cfg]` attribute, `#[cfg_attr]` attribute, `cfg` clause
33+
inside `#[link]` attribute and `cfg!(...)` call against the provided list of expected condition
34+
names. If a name is not present in this list, then `rustc` will report an `unexpected_cfgs` lint
35+
diagnostic. The default diagnostic level for this lint is `Warn`.
36+
37+
If `--check-cfg names(...)` is not specified, then `rustc` will not check references to condition
38+
names.
39+
40+
`--check-cfg names(...)` may be specified more than once. The result is that the list of valid
41+
condition names is merged across all options. It is legal for a condition name to be specified
42+
more than once; redundantly specifying a condition name has no effect.
43+
44+
To enable checking condition names with an empty set of valid condition names, use the following
45+
form. The parentheses are required.
46+
47+
```bash
48+
rustc --check-cfg 'names()'
49+
```
50+
51+
Note that `--check-cfg 'names()'` is _not_ equivalent to omitting the option entirely.
52+
The first form enables checking condition names, while specifying that there are no valid
53+
condition names (outside of the set of well-known names defined by `rustc`). Omitting the
54+
`--check-cfg 'names(...)'` option does not enable checking condition names.
55+
56+
Conditions that are enabled are implicitly valid; it is unnecessary (but legal) to specify a
57+
condition name as both enabled and valid. For example, the following invocations are equivalent:
58+
59+
```bash
60+
# condition names will be checked, and 'has_time_travel' is valid
61+
rustc --cfg 'has_time_travel' --check-cfg 'names()'
62+
63+
# condition names will be checked, and 'has_time_travel' is valid
64+
rustc --cfg 'has_time_travel' --check-cfg 'names(has_time_travel)'
65+
```
66+
67+
In contrast, the following two invocations are _not_ equivalent:
68+
69+
```bash
70+
# condition names will not be checked (because there is no --check-cfg names(...))
71+
rustc --cfg 'has_time_travel'
72+
73+
# condition names will be checked, and 'has_time_travel' is both valid and enabled.
74+
rustc --cfg 'has_time_travel' --check-cfg 'names(has_time_travel)'
75+
```
76+
77+
## The `values(...)` form
78+
79+
The `values(...)` form enables checking the values within list-valued conditions. It has this
80+
form:
81+
82+
```bash
83+
rustc --check-cfg `values(name, "value1", "value2", ... "valueN")'
84+
```
85+
86+
where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal
87+
string. `name` specifies the name of the condition, such as `feature` or `target_os`.
88+
89+
When the `values(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]`
90+
attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]`
91+
and `cfg!(name = "value")` call. It will check that the `"value"` specified is present in the
92+
list of expected values. If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs`
93+
lint diagnostic. The default diagnostic level for this lint is `Warn`.
94+
95+
The form `values()` is an error, because it does not specify a condition name.
96+
97+
To enable checking of values, but to provide an empty set of valid values, use this form:
98+
99+
```bash
100+
rustc --check-cfg `values(name)`
101+
```
102+
103+
The `--check-cfg values(...)` option can be repeated, both for the same condition name and for
104+
different names. If it is repeated for the same condition name, then the sets of values for that
105+
condition are merged together.
106+
107+
## Examples
108+
109+
Consider this command line:
110+
111+
```bash
112+
rustc --check-cfg 'names(feature)' \
113+
--check-cfg 'values(feature,"lion","zebra")' \
114+
--cfg 'feature="lion"' -Z unstable-options \
115+
example.rs
116+
```
117+
118+
This command line indicates that this crate has two features: `lion` and `zebra`. The `lion`
119+
feature is enabled, while the `zebra` feature is disabled. Consider compiling this code:
120+
121+
```rust
122+
// This is expected, and tame_lion() will be compiled
123+
#[cfg(feature = "lion")]
124+
fn tame_lion(lion: Lion) {}
125+
126+
// This is expected, and ride_zebra() will NOT be compiled.
127+
#[cfg(feature = "zebra")]
128+
fn ride_zebra(zebra: Zebra) {}
129+
130+
// This is UNEXPECTED, and will cause a compiler warning (by default).
131+
#[cfg(feature = "platypus")]
132+
fn poke_platypus() {}
133+
134+
// This is UNEXPECTED, because 'feechure' is not a known condition name,
135+
// and will cause a compiler warning (by default).
136+
#[cfg(feechure = "lion")]
137+
fn tame_lion() {}
138+
```
139+
140+
> Note: The `--check-cfg names(feature)` option is necessary only to enable checking the condition
141+
> name, as in the last example. `feature` is a well-known (always-expected) condition name, and so
142+
> it is not necessary to specify it in a `--check-cfg 'names(...)'` option. That option can be
143+
> shortened to > `--check-cfg names()` in order to enable checking well-known condition names.
144+
145+
### Example: Checking condition names, but not values
146+
147+
```bash
148+
# This turns on checking for condition names, but not values, such as 'feature' values.
149+
rustc --check-cfg 'names(is_embedded, has_feathers)' \
150+
--cfg has_feathers --cfg 'feature = "zapping"' -Z unstable-options
151+
```
152+
153+
```rust
154+
#[cfg(is_embedded)] // This is expected as "is_embedded" was provided in names()
155+
fn do_embedded() {}
156+
157+
#[cfg(has_feathers)] // This is expected as "has_feathers" was provided in names()
158+
fn do_features() {}
159+
160+
#[cfg(has_mumble_frotz)] // This is UNEXPECTED because names checking is enable and
161+
// "has_mumble_frotz" was not provided in names()
162+
fn do_mumble_frotz() {}
163+
164+
#[cfg(feature = "lasers")] // This doesn't raise a warning, because values checking for "feature"
165+
// was never used
166+
fn shoot_lasers() {}
167+
```
168+
169+
### Example: Checking feature values, but not condition names
170+
171+
```bash
172+
# This turns on checking for feature values, but not for condition names.
173+
rustc --check-cfg 'values(feature, "zapping", "lasers")' \
174+
--cfg 'feature="zapping"' -Z unstable-options
175+
```
176+
177+
```rust
178+
#[cfg(is_embedded)] // This is doesn't raise a warning, because names checking was not
179+
// enable (ie not names())
180+
fn do_embedded() {}
181+
182+
#[cfg(has_feathers)] // Same as above, --check-cfg names(...) was never used so no name
183+
// checking is performed
184+
fn do_features() {}
185+
186+
187+
#[cfg(feature = "lasers")] // This is expected, "lasers" is in the values(feature) list
188+
fn shoot_lasers() {}
189+
190+
#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in the
191+
// --check-cfg values(feature) list
192+
fn write_shakespeare() {}
193+
```
194+
195+
### Example: Checking both condition names and feature values
196+
197+
```bash
198+
# This turns on checking for feature values and for condition names.
199+
rustc --check-cfg 'names(is_embedded, has_feathers)' \
200+
--check-cfg 'values(feature, "zapping", "lasers")' \
201+
--cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options
202+
```
203+
204+
```rust
205+
#[cfg(is_embedded)] // This is expected because "is_embedded" was provided in names()
206+
fn do_embedded() {}
207+
208+
#[cfg(has_feathers)] // This is expected because "has_feathers" was provided in names()
209+
fn do_features() {}
210+
211+
#[cfg(has_mumble_frotz)] // This is UNEXPECTED, because has_mumble_frotz is not in the
212+
// --check-cfg names(...) list
213+
fn do_mumble_frotz() {}
214+
215+
#[cfg(feature = "lasers")] // This is expected, "lasers" is in the values(feature) list
216+
fn shoot_lasers() {}
217+
218+
#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in
219+
// the values(feature) list
220+
fn write_shakespear() {}
221+
```

0 commit comments

Comments
 (0)