mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 08:53:35 +00:00
Auto merge of #124209 - Urgau:check-cfg-more-friendly-docs, r=ehuss
Make check-cfg docs more user-friendly This PR improves the `--check-cfg` to make them more user-friendly by: - explaining the purpose of the feature - removing the "form" jargon - making it (bit) less formal and more "friendly" - making the doc less cluttered - and by fixing (the width and flags) of the examples `@rustbot` label +F-check-cfg
This commit is contained in:
commit
ce652dbb9a
@ -1,18 +1,29 @@
|
||||
# Checking conditional configurations
|
||||
|
||||
`rustc` accepts the `--check-cfg` option, which specifies whether to check conditions and how to
|
||||
check them. The `--check-cfg` option takes a value, called the _check cfg specification_.
|
||||
This specification has one form:
|
||||
`rustc` supports checking that every _reachable_[^reachable] `#[cfg]` matches a list of the
|
||||
expected config names and values.
|
||||
|
||||
1. `--check-cfg cfg(...)` mark a configuration and it's expected values as expected.
|
||||
This can help with verifying that the crate is correctly handling conditional compilation for
|
||||
different target platforms or features. It ensures that the cfg settings are consistent between
|
||||
what is intended and what is used, helping to catch potential bugs or errors early in the
|
||||
development process.
|
||||
|
||||
*No implicit expectation is added when using `--cfg`. Users are expected to
|
||||
pass all expected names and values using the _check cfg specification_.*
|
||||
In order to accomplish that goal, `rustc` accepts the `--check-cfg` flag, which specifies
|
||||
whether to check conditions and how to check them.
|
||||
|
||||
## The `cfg(...)` form
|
||||
> **Note:** No implicit expectation is added when using `--cfg`. Users are expected to
|
||||
pass all expected names and values using the _check cfg specification_.
|
||||
|
||||
The `cfg(...)` form enables checking the values within list-valued conditions. It has this
|
||||
basic form:
|
||||
[^reachable]: `rustc` promises to at least check reachable `#[cfg]`, and while non-reachable
|
||||
`#[cfg]` are not currently checked, they may well be checked in the future without it being a
|
||||
breaking change.
|
||||
|
||||
## Specifying expected names and values
|
||||
|
||||
To specify expected names and values, the _check cfg specification_ provides the `cfg(...)`
|
||||
option which enables specifying for an expected config name and it's expected values.
|
||||
|
||||
It has this basic form:
|
||||
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(name, values("value1", "value2", ... "valueN"))'
|
||||
@ -20,15 +31,20 @@ rustc --check-cfg 'cfg(name, values("value1", "value2", ... "valueN"))'
|
||||
|
||||
where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal
|
||||
string. `name` specifies the name of the condition, such as `feature` or `my_cfg`.
|
||||
`"value"` specify one of the value of that condition name.
|
||||
|
||||
When the `cfg(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]`
|
||||
attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]`
|
||||
attribute and `cfg!(name = "value")` macro call. It will check that the `"value"` specified is
|
||||
present in the list of expected values. If `"value"` is not in it, then `rustc` will report an
|
||||
`unexpected_cfgs` lint diagnostic. The default diagnostic level for this lint is `Warn`.
|
||||
When the `cfg(...)` option is specified, `rustc` will check every[^reachable]:
|
||||
- `#[cfg(name = "value")]` attribute
|
||||
- `#[cfg_attr(name = "value")]` attribute
|
||||
- `#[link(name = "a", cfg(name = "value"))]` attribute
|
||||
- `cfg!(name = "value")` macro call
|
||||
|
||||
*The command line `--cfg` arguments are currently *NOT* checked but may very well be checked in
|
||||
the future.*
|
||||
> *The command line `--cfg` arguments are currently NOT checked but may very well be checked
|
||||
in the future.*
|
||||
|
||||
`rustc` will check that the `"value"` specified is present in the list of expected values.
|
||||
If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs` lint diagnostic.
|
||||
The default diagnostic level for this lint is `Warn`.
|
||||
|
||||
To check for the _none_ value (ie `#[cfg(foo)]`) one can use the `none()` predicate inside
|
||||
`values()`: `values(none())`. It can be followed or preceded by any number of `"value"`.
|
||||
@ -43,12 +59,12 @@ rustc --check-cfg 'cfg(name, values(none()))'
|
||||
|
||||
To enable checking of name but not values, use one of these forms:
|
||||
|
||||
- No expected values (_will lint on every value_):
|
||||
- No expected values (_will lint on every value of `name`_):
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(name, values())'
|
||||
```
|
||||
|
||||
- Unknown expected values (_will never lint_):
|
||||
- Unknown expected values (_will never lint on value of `name`_):
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(name, values(any()))'
|
||||
```
|
||||
@ -59,17 +75,26 @@ To avoid repeating the same set of values, use this form:
|
||||
rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'
|
||||
```
|
||||
|
||||
To enable checking without specifying any names or values, use this form:
|
||||
|
||||
```bash
|
||||
rustc --check-cfg 'cfg()'
|
||||
```
|
||||
|
||||
The `--check-cfg cfg(...)` option can be repeated, both for the same condition name and for
|
||||
different names. If it is repeated for the same condition name, then the sets of values for that
|
||||
condition are merged together (precedence is given to `values(any())`).
|
||||
|
||||
> To help out an equivalence table between `--cfg` arguments and `--check-cfg` is available
|
||||
[down below](#equivalence-table-with---cfg).
|
||||
|
||||
## Well known names and values
|
||||
|
||||
`rustc` has a internal list of well known names and their corresponding values.
|
||||
Those well known names and values follows the same stability as what they refer to.
|
||||
`rustc` maintains a list of well-known names and their corresponding values in order to avoid
|
||||
the need to specify them manually.
|
||||
|
||||
Well known names and values checking is always enabled as long as at least one
|
||||
`--check-cfg` argument is present.
|
||||
Well known names and values are implicitly added as long as at least one `--check-cfg` argument
|
||||
is present.
|
||||
|
||||
As of `2024-05-06T`, the list of known names is as follows:
|
||||
|
||||
@ -109,11 +134,9 @@ As of `2024-05-06T`, the list of known names is as follows:
|
||||
Like with `values(any())`, well known names checking can be disabled by passing `cfg(any())`
|
||||
as argument to `--check-cfg`.
|
||||
|
||||
## Examples
|
||||
## Equivalence table with `--cfg`
|
||||
|
||||
### Equivalence table
|
||||
|
||||
This table describe the equivalence of a `--cfg` argument to a `--check-cfg` argument.
|
||||
This table describe the equivalence between a `--cfg` argument to a `--check-cfg` argument.
|
||||
|
||||
| `--cfg` | `--check-cfg` |
|
||||
|-------------------------------|------------------------------------------------------------|
|
||||
@ -125,40 +148,42 @@ This table describe the equivalence of a `--cfg` argument to a `--check-cfg` arg
|
||||
| `--cfg foo="1" --cfg bar="2"` | `--check-cfg=cfg(foo, values("1")) --check-cfg=cfg(bar, values("2"))` |
|
||||
| `--cfg foo --cfg foo="bar"` | `--check-cfg=cfg(foo, values(none(), "bar"))` |
|
||||
|
||||
## Examples
|
||||
|
||||
### Example: Cargo-like `feature` example
|
||||
|
||||
Consider this command line:
|
||||
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(feature, values("lion", "zebra"))' \
|
||||
--cfg 'feature="lion"' -Z unstable-options example.rs
|
||||
--cfg 'feature="lion"' example.rs
|
||||
```
|
||||
|
||||
This command line indicates that this crate has two features: `lion` and `zebra`. The `lion`
|
||||
> This command line indicates that this crate has two features: `lion` and `zebra`. The `lion`
|
||||
feature is enabled, while the `zebra` feature is disabled.
|
||||
Given the `--check-cfg` arguments, exhaustive checking of names and
|
||||
values are enabled.
|
||||
|
||||
`example.rs`:
|
||||
```rust
|
||||
#[cfg(feature = "lion")] // This condition is expected, as "lion" is an expected value of `feature`
|
||||
#[cfg(feature = "lion")] // This condition is expected, as "lion" is an
|
||||
// expected value of `feature`
|
||||
fn tame_lion(lion: Lion) {}
|
||||
|
||||
#[cfg(feature = "zebra")] // This condition is expected, as "zebra" is an expected value of `feature`
|
||||
// but the condition will still evaluate to false
|
||||
// since only --cfg feature="lion" was passed
|
||||
#[cfg(feature = "zebra")] // This condition is expected, as "zebra" is an expected
|
||||
// value of `feature` but the condition will evaluate
|
||||
// to false since only --cfg feature="lion" was passed
|
||||
fn ride_zebra(z: Zebra) {}
|
||||
|
||||
#[cfg(feature = "platypus")] // This condition is UNEXPECTED, as "platypus" is NOT an expected value of
|
||||
// `feature` and will cause a compiler warning (by default).
|
||||
#[cfg(feature = "platypus")] // This condition is UNEXPECTED, as "platypus" is NOT
|
||||
// an expected value of `feature` and will cause a
|
||||
// the compiler to emit the `unexpected_cfgs` lint
|
||||
fn poke_platypus() {}
|
||||
|
||||
#[cfg(feechure = "lion")] // This condition is UNEXPECTED, as 'feechure' is NOT a expected condition
|
||||
// name, no `cfg(feechure, ...)` was passed in `--check-cfg`
|
||||
#[cfg(feechure = "lion")] // This condition is UNEXPECTED, as 'feechure' is NOT
|
||||
// a expected condition name, no `cfg(feechure, ...)`
|
||||
// was passed in `--check-cfg`
|
||||
fn tame_lion() {}
|
||||
|
||||
#[cfg(windows = "unix")] // This condition is UNEXPECTED, as while 'windows' is a well known
|
||||
// condition name, it doesn't expect any values
|
||||
#[cfg(windows = "unix")] // This condition is UNEXPECTED, as the well known
|
||||
// 'windows' cfg doesn't expect any values
|
||||
fn tame_windows() {}
|
||||
```
|
||||
|
||||
@ -167,25 +192,28 @@ fn tame_windows() {}
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(is_embedded, has_feathers)' \
|
||||
--check-cfg 'cfg(feature, values("zapping", "lasers"))' \
|
||||
--cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options
|
||||
--cfg has_feathers --cfg 'feature="zapping"'
|
||||
```
|
||||
|
||||
```rust
|
||||
#[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was provided in --check-cfg
|
||||
fn do_embedded() {} // and doesn't take any value
|
||||
#[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was
|
||||
// provided in --check-cfg and doesn't take any value
|
||||
fn do_embedded() {}
|
||||
|
||||
#[cfg(has_feathers)] // This condition is expected, as 'has_feathers' was provided in --check-cfg
|
||||
fn do_features() {} // and doesn't take any value
|
||||
#[cfg(has_feathers)] // This condition is expected, as 'has_feathers' was
|
||||
// provided in --check-cfg and doesn't take any value
|
||||
fn do_features() {}
|
||||
|
||||
#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz' was NEVER provided
|
||||
// in any --check-cfg arguments
|
||||
#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz'
|
||||
// was NEVER provided in any --check-cfg arguments
|
||||
fn do_mumble_frotz() {}
|
||||
|
||||
#[cfg(feature = "lasers")] // This condition is expected, as "lasers" is an expected value of `feature`
|
||||
#[cfg(feature = "lasers")] // This condition is expected, as "lasers" is an
|
||||
// expected value of `feature`
|
||||
fn shoot_lasers() {}
|
||||
|
||||
#[cfg(feature = "monkeys")] // This condition is UNEXPECTED, as "monkeys" is NOT an expected value of
|
||||
// `feature`
|
||||
#[cfg(feature = "monkeys")] // This condition is UNEXPECTED, as "monkeys" is NOT
|
||||
// an expected value of `feature`
|
||||
fn write_shakespeare() {}
|
||||
```
|
||||
|
||||
@ -193,24 +221,25 @@ fn write_shakespeare() {}
|
||||
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \
|
||||
--cfg has_feathers -Z unstable-options
|
||||
--cfg has_feathers
|
||||
```
|
||||
|
||||
```rust
|
||||
#[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was provided in --check-cfg
|
||||
// as condition name
|
||||
#[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was
|
||||
// provided in --check-cfg as condition name
|
||||
fn do_embedded() {}
|
||||
|
||||
#[cfg(has_feathers)] // This condition is expected, as "has_feathers" was provided in --check-cfg
|
||||
// as condition name
|
||||
#[cfg(has_feathers)] // This condition is expected, as "has_feathers" was
|
||||
// provided in --check-cfg as condition name
|
||||
fn do_features() {}
|
||||
|
||||
#[cfg(has_feathers = "zapping")] // This condition is expected, as "has_feathers" was provided in
|
||||
// and because *any* values is expected for 'has_feathers' no
|
||||
#[cfg(has_feathers = "zapping")] // This condition is expected, as "has_feathers"
|
||||
// was provided and because *any* values is
|
||||
// expected for 'has_feathers' no
|
||||
// warning is emitted for the value "zapping"
|
||||
fn do_zapping() {}
|
||||
|
||||
#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz' was not provided
|
||||
// in any --check-cfg arguments
|
||||
#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz'
|
||||
// was not provided in any --check-cfg arguments
|
||||
fn do_mumble_frotz() {}
|
||||
```
|
||||
|
@ -19,9 +19,15 @@ For examples, `--cfg 'verbose'` or `--cfg 'feature="serde"'`. These correspond
|
||||
to `#[cfg(verbose)]` and `#[cfg(feature = "serde")]` respectively.
|
||||
|
||||
<a id="option-check-cfg"></a>
|
||||
## `--check-cfg`: enables checking conditional configurations
|
||||
## `--check-cfg`: configure compile-time checking of conditional compilation
|
||||
|
||||
This flag enables checking conditional configurations of the crate at compile-time,
|
||||
specifically it helps configure the set of expected cfg names and values, in order
|
||||
to check that every _reachable_ `#[cfg]` matches the expected config names and values.
|
||||
|
||||
This is different from the `--cfg` flag above which activates some config but do
|
||||
not expect them. This is useful to prevent stalled conditions, typos, ...
|
||||
|
||||
This flag will enable checking conditional configurations.
|
||||
Refer to the [Checking conditional configurations](check-cfg.md) of this book
|
||||
for further details and explanation.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user