@@ -4,189 +4,211 @@ The tracking issue for this feature is: [#82450](https://github.com/rust-lang/ru
4
4
5
5
------------------------
6
6
7
- This feature allows you to enable complete or partial checking of configuration.
7
+ This feature enables checking of conditional configuration.
8
8
9
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.
10
+ check them. The ` --check-cfg ` option takes a value, called the _ check cfg specification_ .
11
+ This specification has one form:
12
12
13
- ` --check-cfg ` option take one form:
13
+ 1 . ` --check-cfg cfg(...) ` mark a configuration and it's expected values as expected.
14
14
15
- 1 . ` --check-cfg cfg(...) ` enables checking the values within list-valued conditions.
16
-
17
- NOTE: No implicit expectation is added when using ` --cfg ` for both forms. Users are expected to
18
- pass all expected names and values using ` cfg(...) ` .
15
+ * No implicit expectation is added when using ` --cfg ` . Users are expected to
16
+ pass all expected names and values using the _ check cfg specification_ .*
19
17
20
18
## The ` cfg(...) ` form
21
19
22
20
The ` cfg(...) ` form enables checking the values within list-valued conditions. It has this
23
21
basic form:
24
22
25
23
``` bash
26
- rustc --check-cfg ' cfg(name1, ..., nameN , values("value1", "value2", ... "valueN"))'
24
+ rustc --check-cfg ' cfg(name , values("value1", "value2", ... "valueN"))'
27
25
```
28
26
29
27
where ` name ` is a bare identifier (has no quotes) and each ` "value" ` term is a quoted literal
30
28
string. ` name ` specifies the name of the condition, such as ` feature ` or ` my_cfg ` .
31
29
32
30
When the ` cfg(...) ` option is specified, ` rustc ` will check every ` #[cfg(name = "value")] `
33
31
attribute, ` #[cfg_attr(name = "value")] ` attribute, ` #[link(name = "a", cfg(name = "value"))] `
34
- and ` cfg!(name = "value") ` call. It will check that the ` "value" ` specified is present in the
35
- list of expected values. If ` "value" ` is not in it, then ` rustc ` will report an ` unexpected_cfgs `
36
- lint diagnostic. The default diagnostic level for this lint is ` Warn ` .
32
+ attribute and ` cfg!(name = "value") ` macro call. It will check that the ` "value" ` specified is
33
+ present in the list of expected values. If ` "value" ` is not in it, then ` rustc ` will report an
34
+ ` unexpected_cfgs ` lint diagnostic. The default diagnostic level for this lint is ` Warn ` .
37
35
38
- The command line ` --cfg ` arguments are currently * NOT* checked but may very well be checked in
39
- the future.
36
+ * The command line ` --cfg ` arguments are currently * NOT* checked but may very well be checked in
37
+ the future.*
40
38
41
- To enable checking of values, but to provide an empty set of expected values, use these forms:
39
+ To enable checking of values, but to provide an * none* /empty set of expected values
40
+ (ie. expect ` #[cfg(name)] ` ), use these forms:
42
41
43
42
``` bash
44
- rustc --check-cfg ' cfg(name1, ..., nameN )'
45
- rustc --check-cfg ' cfg(name1, ..., nameN , values())'
43
+ rustc --check-cfg ' cfg(name )'
44
+ rustc --check-cfg ' cfg(name , values())'
46
45
```
47
46
48
47
To enable checking of name but not values (i.e. unknown expected values), use this form:
49
48
50
49
``` bash
51
- rustc --check-cfg ' cfg(name1, ..., nameN, values(any()))'
50
+ rustc --check-cfg ' cfg(name, values(any()))'
51
+ ```
52
+
53
+ To avoid repeating the same set of values, use this form:
54
+
55
+ ``` bash
56
+ rustc --check-cfg ' cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'
52
57
```
53
58
54
59
The ` --check-cfg cfg(...) ` option can be repeated, both for the same condition name and for
55
60
different names. If it is repeated for the same condition name, then the sets of values for that
56
- condition are merged together (presedence is given to ` any() ` ).
61
+ condition are merged together (precedence is given to ` values( any() )` ).
57
62
58
63
## Well known names and values
59
64
60
65
` rustc ` has a internal list of well known names and their corresponding values.
61
66
Those well known names and values follows the same stability as what they refer to.
62
67
63
- Well known values checking is always enabled as long as a ` --check-cfg ` argument is present.
68
+ Well known names and values checking is always enabled as long as at least one
69
+ ` --check-cfg ` argument is present.
70
+
71
+ As of ` 2024-01-09T ` , the list of known names is as follows:
72
+
73
+ <!-- - See CheckCfg::fill_well_known in compiler/rustc_session/src/config.rs -->
74
+
75
+ - ` debug_assertions `
76
+ - ` doc `
77
+ - ` doctest `
78
+ - ` miri `
79
+ - ` overflow_checks `
80
+ - ` panic `
81
+ - ` proc_macro `
82
+ - ` relocation_model `
83
+ - ` sanitize `
84
+ - ` sanitizer_cfi_generalize_pointers `
85
+ - ` sanitizer_cfi_normalize_integers `
86
+ - ` target_abi `
87
+ - ` target_arch `
88
+ - ` target_endian `
89
+ - ` target_env `
90
+ - ` target_family `
91
+ - ` target_feature `
92
+ - ` target_has_atomic `
93
+ - ` target_has_atomic_equal_alignment `
94
+ - ` target_has_atomic_load_store `
95
+ - ` target_os `
96
+ - ` target_pointer_width `
97
+ - ` target_thread_local `
98
+ - ` target_vendor `
99
+ - ` test `
100
+ - ` unix `
101
+ - ` windows `
102
+
103
+ Like with ` values(any()) ` , well known names checking can be disabled by passing ` cfg(any()) `
104
+ as argument to ` --check-cfg ` .
64
105
65
- Well known names checking is always enable as long as a ` --check-cfg ` argument is present
66
- ** unless** any ` cfg(any()) ` argument is passed.
106
+ ## Examples
67
107
68
- To disable checking of well known names, use this form:
108
+ ### Equivalence table
69
109
70
- ``` bash
71
- rustc --check-cfg ' cfg(any())'
72
- ```
110
+ This table describe the equivalence of a ` --cfg ` argument to a ` --check-cfg ` argument.
73
111
74
- NOTE: If one want to enable values and names checking without having any cfg to declare, one
75
- can use an empty ` cfg() ` argument.
112
+ | ` --cfg ` | ` --check-cfg ` |
113
+ | -----------------------------| ----------------------------------------------------------|
114
+ | * nothing* | * nothing* or ` --check-cfg=cfg() ` (to enable the checking) |
115
+ | ` --cfg foo ` | ` --check-cfg=cfg(foo) or --check-cfg=cfg(foo, values()) ` |
116
+ | ` --cfg foo="" ` | ` --check-cfg=cfg(foo, values("")) ` |
117
+ | ` --cfg foo="bar" ` | ` --check-cfg=cfg(foo, values("bar")) ` |
118
+ | ` --cfg foo="1" --cfg foo="2" ` | ` --check-cfg=cfg(foo, values("1", "2")) ` |
119
+ | ` --cfg foo="1" --cfg bar="2" ` | ` --check-cfg=cfg(foo, values("1")) --check-cfg=cfg(bar, values("2")) ` |
120
+ | ` --cfg foo --cfg foo="bar" ` | ` --check-cfg=cfg(foo) --check-cfg=cfg(foo, values("bar")) ` |
76
121
77
- ## Examples
122
+ NOTE: There is (currently) no way to express that a condition name is expected but no (!= none)
123
+ values are expected. Passing an empty ` values() ` means * (none)* in the sense of ` #[cfg(foo)] `
124
+ with no value. Users are expected to NOT pass a ` --check-cfg ` with that condition name.
125
+
126
+ ### Example: Cargo-like ` feature ` example
78
127
79
128
Consider this command line:
80
129
81
130
``` bash
82
131
rustc --check-cfg ' cfg(feature, values("lion", "zebra"))' \
83
- --cfg ' feature="lion"' -Z unstable-options \
84
- example.rs
132
+ --cfg ' feature="lion"' -Z unstable-options example.rs
85
133
```
86
134
87
135
This command line indicates that this crate has two features: ` lion ` and ` zebra ` . The ` lion `
88
- feature is enabled, while the ` zebra ` feature is disabled. Exhaustive checking of names and
89
- values are enabled by default. Consider compiling this code:
136
+ feature is enabled, while the ` zebra ` feature is disabled.
137
+ Given the ` --check-cfg ` arguments, exhaustive checking of names and
138
+ values are enabled.
90
139
140
+ ` example.rs ` :
91
141
``` rust
92
- // This is expected, and tame_lion() will be compiled
93
- #[cfg(feature = " lion" )]
142
+ #[cfg(feature = " lion" )] // This condition is expected, as "lion" is an expected value of `feature`
94
143
fn tame_lion (lion : Lion ) {}
95
144
96
- // This is expected, and ride_zebra() will NOT be compiled.
97
- #[cfg(feature = " zebra" )]
98
- fn ride_zebra (zebra : Zebra ) {}
145
+ #[cfg(feature = " zebra" )] // This condition is expected, as "zebra" is an expected value of `feature`
146
+ // but the condition will still evaluate to false
147
+ // since only --cfg feature="lion" was passed
148
+ fn ride_zebra (z : Zebra ) {}
99
149
100
- // This is UNEXPECTED, and will cause a compiler warning (by default).
101
- #[cfg( feature = " platypus " )]
150
+ #[cfg(feature = " platypus " )] // This condition is UNEXPECTED, as "platypus" is NOT an expected value of
151
+ // ` feature` and will cause a compiler warning (by default).
102
152
fn poke_platypus () {}
103
153
104
- // This is UNEXPECTED, because 'feechure' is not a known condition name,
105
- // and will cause a compiler warning (by default).
106
- #[cfg(feechure = " lion" )]
154
+ #[cfg(feechure = " lion" )] // This condition is UNEXPECTED, as 'feechure' is NOT a expected condition
155
+ // name, no `cfg(feechure, ...)` was passed in `--check-cfg`
107
156
fn tame_lion () {}
108
157
109
- // This is UNEXPECTED, because 'windows' is a well known condition name,
110
- // and because 'windows' doesn't take any values,
111
- // and will cause a compiler warning (by default).
112
- #[cfg(windows = " unix" )]
158
+ #[cfg(windows = " unix" )] // This condition is UNEXPECTED, as while 'windows' is a well known
159
+ // condition name, it doens't expect any values
113
160
fn tame_windows () {}
114
161
```
115
162
116
- ### Example: Checking condition names, but not values
163
+ ### Example: Multiple names and values
117
164
118
165
``` bash
119
- # This turns on checking for condition names, but not values, such as 'feature' values.
120
- rustc --check-cfg ' cfg(is_embedded, has_feathers, values(any() ))' \
121
- --cfg has_feathers -Z unstable-options
166
+ rustc --check-cfg ' cfg(is_embedded, has_feathers) ' \
167
+ --check-cfg ' cfg(feature, values("zapping", "lasers" ))' \
168
+ --cfg has_feathers --cfg ' feature="zapping" ' - Z unstable-options
122
169
```
123
170
124
171
``` rust
125
- #[cfg(is_embedded)] // This is expected as "is_embedded" was provided in cfg()
126
- fn do_embedded () {} // and because names exhaustiveness was not disabled
127
-
128
- #[cfg(has_feathers)] // This is expected as "has_feathers" was provided in cfg()
129
- fn do_features () {} // and because names exhaustiveness was not disabled
172
+ #[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was provided in --check-cfg
173
+ fn do_embedded () {} // and doesn't take any value
130
174
131
- #[cfg(has_feathers = " zapping" )] // This is expected as "has_feathers" was provided in cfg()
132
- // and because no value checking was enable for "has_feathers"
133
- // no warning is emitted for the value "zapping"
134
- fn do_zapping () {}
175
+ #[cfg(has_feathers)] // This condition is expected, as 'has_feathers' was provided in --check-cfg
176
+ fn do_features () {} // and doesn't take any value
135
177
136
- #[cfg(has_mumble_frotz)] // This is UNEXPECTED because names checking is enable and
137
- // "has_mumble_frotz" was not provided in cfg()
178
+ #[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz' was NEVER provided
179
+ // in any --check- cfg arguments
138
180
fn do_mumble_frotz () {}
139
- ```
140
-
141
- ### Example: Checking feature values, but not condition names
142
181
143
- ``` bash
144
- # This turns on checking for feature values, but not for condition names.
145
- rustc --check-cfg ' cfg(feature, values("zapping", "lasers"))' \
146
- --check-cfg ' cfg(any())' \
147
- --cfg ' feature="zapping"' -Z unstable-options
148
- ```
149
-
150
- ``` rust
151
- #[cfg(is_embedded)] // This is doesn't raise a warning, because names checking was
152
- // disabled by 'cfg(any())'
153
- fn do_embedded () {}
154
-
155
- #[cfg(has_feathers)] // Same as above, 'cfg(any())' was provided so no name
156
- // checking is performed
157
- fn do_features () {}
158
-
159
- #[cfg(feature = " lasers" )] // This is expected, "lasers" is in the cfg(feature) list
182
+ #[cfg(feature = " lasers" )] // This condition is expected, as "lasers" is an expected value of `feature`
160
183
fn shoot_lasers () {}
161
184
162
- #[cfg(feature = " monkeys" )] // This is UNEXPECTED, because "monkeys" is not in the
163
- // cfg( feature) list
185
+ #[cfg(feature = " monkeys" )] // This condition is UNEXPECTED, as "monkeys" is NOT an expected value of
186
+ // ` feature`
164
187
fn write_shakespeare () {}
165
188
```
166
189
167
- ### Example: Checking both condition names and feature values
190
+ ### Example: Condition names without values
168
191
169
192
``` bash
170
- # This turns on checking for feature values and for condition names.
171
- rustc --check-cfg ' cfg(is_embedded, has_feathers)' \
172
- --check-cfg ' cfg(feature, values("zapping", "lasers"))' \
173
- --cfg has_feathers --cfg ' feature="zapping"' -Z unstable-options
193
+ rustc --check-cfg ' cfg(is_embedded, has_feathers, values(any()))' \
194
+ --cfg has_feathers -Z unstable-options
174
195
```
175
196
176
197
``` rust
177
- #[cfg(is_embedded)] // This is expected because "is_embedded" was provided in cfg()
178
- fn do_embedded () {} // and doesn't take any value
179
-
180
- #[cfg(has_feathers)] // This is expected because "has_feathers" was provided in cfg()
181
- fn do_features () {} // and deosn't take any value
198
+ #[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was provided in --check-cfg
199
+ // as condition name
200
+ fn do_embedded () {}
182
201
183
- #[cfg(has_mumble_frotz)] // This is UNEXPECTED, because "has_mumble_frotz" was never provided
184
- fn do_mumble_frotz () {}
202
+ #[cfg(has_feathers)] // This condition is expected, as "has_feathers" was provided in --check-cfg
203
+ // as condition name
204
+ fn do_features () {}
185
205
186
- #[cfg(feature = " lasers" )] // This is expected, "lasers" is in the cfg(feature) list
187
- fn shoot_lasers () {}
206
+ #[cfg(has_feathers = " zapping" )] // This condition is expected, as "has_feathers" was provided in
207
+ // and because *any* values is expected for 'has_feathers' no
208
+ // warning is emitted for the value "zapping"
209
+ fn do_zapping () {}
188
210
189
- #[cfg(feature = " monkeys " )] // This is UNEXPECTED, because "monkeys" is not in
190
- // the cfg(feature) list
191
- fn write_shakespeare () {}
211
+ #[cfg(has_mumble_frotz )] // This condition is UNEXPECTED, as 'has_mumble_frotz' was not provided
212
+ // in any --check- cfg arguments
213
+ fn do_mumble_frotz () {}
192
214
```
0 commit comments