Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 9 pull requests #119767

Merged
merged 26 commits into from
Jan 9, 2024
Merged
Changes from 2 commits
Commits
Show all changes
26 commits
Select commit Hold shift click to select a range
bc6a5c7
std: getrandom simplification for freebsd.
devnexen Dec 8, 2023
2c088f9
Disallow reference to `static mut` for expressions
obeis Dec 22, 2023
70ba4d1
Disallow reference to `static mut` for statements
obeis Dec 22, 2023
a82fd2b
Call `maybe_expr_static_mut` inside `resolve_expr`
obeis Dec 22, 2023
e36f7b7
Call `maybe_stmt_static_mut` inside `resolve_stmt`
obeis Dec 22, 2023
18edf9a
Add test for `E0796` and `static_mut_ref` lint
obeis Dec 22, 2023
5617361
don't reexport atomic::ordering via rustc_data_structures, use std im…
klensy Jan 2, 2024
a8aa687
Update test for `E0796` and `static_mut_ref` lint
obeis Dec 22, 2023
4071572
Merge dead bb pruning and unreachable bb deduplication.
cjgillot Jan 7, 2024
e61be1b
rustdoc-search: reuse empty map/array in function signatures
notriddle Jan 8, 2024
8356802
Move promote_consts back to rustc_mir_transform.
cjgillot May 20, 2023
cae0dc2
Simplify code flow.
cjgillot May 20, 2023
5d6463c
Make match exhaustive.
cjgillot Jan 8, 2024
a2b765f
Remove `-Zdont-buffer-diagnostics`.
nnethercote Jan 7, 2024
c3cd657
rustdoc-search: intern function search types
notriddle Jan 8, 2024
c8ded52
GNU/Hurd: unconditionally use inline stack probes
erikdesjardins Jan 9, 2024
3611014
Rework and improve unstable documentation of check-cfg
Urgau Dec 22, 2023
4a24b5b
Rollup merge of #117556 - obeis:static-mut-ref-lint, r=davidtwco
GuillaumeGomez Jan 9, 2024
df2f4ae
Rollup merge of #118748 - devnexen:fbsd_getrandom_simpl, r=Nilstrieb,…
GuillaumeGomez Jan 9, 2024
5c9a8d7
Rollup merge of #119282 - Urgau:check-cfg-rework-unstable-doc, r=John…
GuillaumeGomez Jan 9, 2024
d3574be
Rollup merge of #119527 - klensy:ordering, r=compiler-errors
GuillaumeGomez Jan 9, 2024
72fdaf5
Rollup merge of #119668 - cjgillot:transform-promote, r=oli-obk
GuillaumeGomez Jan 9, 2024
9b90541
Rollup merge of #119699 - cjgillot:simplify-unreachable, r=oli-obk
GuillaumeGomez Jan 9, 2024
b0aa3d8
Rollup merge of #119723 - nnethercote:rm-Zdont-buffer-diagnostics, r=…
GuillaumeGomez Jan 9, 2024
f9cadb9
Rollup merge of #119756 - notriddle:notriddle/reuse-map, r=GuillaumeG…
GuillaumeGomez Jan 9, 2024
f41d773
Rollup merge of #119758 - erikdesjardins:hurd, r=petrochenkov
GuillaumeGomez Jan 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
224 changes: 123 additions & 101 deletions src/doc/unstable-book/src/compiler-flags/check-cfg.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,189 4,211 @@ The tracking issue for this feature is: [#82450](https://github.com/rust-lang/ru

------------------------

This feature allows you to enable complete or partial checking of configuration.
This feature enables checking of conditional configuration.

`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_. The
check cfg specification is parsed using the Rust metadata syntax, just as the `--cfg` option is.
check them. The `--check-cfg` option takes a value, called the _check cfg specification_.
This specification has one form:

`--check-cfg` option take one form:
1. `--check-cfg cfg(...)` mark a configuration and it's expected values as expected.

1. `--check-cfg cfg(...)` enables checking the values within list-valued conditions.

NOTE: No implicit expectation is added when using `--cfg` for both forms. Users are expected to
pass all expected names and values using `cfg(...)`.
*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

The `cfg(...)` form enables checking the values within list-valued conditions. It has this
basic form:

```bash
rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'
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`.

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"))]`
and `cfg!(name = "value")` 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`.
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`.

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.*

To enable checking of values, but to provide an empty set of expected values, use these forms:
To enable checking of values, but to provide an *none*/empty set of expected values
(ie. expect `#[cfg(name)]`), use these forms:

```bash
rustc --check-cfg 'cfg(name1, ..., nameN)'
rustc --check-cfg 'cfg(name1, ..., nameN, values())'
rustc --check-cfg 'cfg(name)'
rustc --check-cfg 'cfg(name, values())'
```

To enable checking of name but not values (i.e. unknown expected values), use this form:

```bash
rustc --check-cfg 'cfg(name1, ..., nameN, values(any()))'
rustc --check-cfg 'cfg(name, values(any()))'
```

To avoid repeating the same set of values, use this form:

```bash
rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'
```

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 (presedence is given to `any()`).
condition are merged together (precedence is given to `values(any())`).

## 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.

Well known values checking is always enabled as long as a `--check-cfg` argument is present.
Well known names and values checking is always enabled as long as at least one
`--check-cfg` argument is present.

As of `2024-01-09T`, the list of known names is as follows:

<!--- See CheckCfg::fill_well_known in compiler/rustc_session/src/config.rs -->

- `debug_assertions`
- `doc`
- `doctest`
- `miri`
- `overflow_checks`
- `panic`
- `proc_macro`
- `relocation_model`
- `sanitize`
- `sanitizer_cfi_generalize_pointers`
- `sanitizer_cfi_normalize_integers`
- `target_abi`
- `target_arch`
- `target_endian`
- `target_env`
- `target_family`
- `target_feature`
- `target_has_atomic`
- `target_has_atomic_equal_alignment`
- `target_has_atomic_load_store`
- `target_os`
- `target_pointer_width`
- `target_thread_local`
- `target_vendor`
- `test`
- `unix`
- `windows`

Like with `values(any())`, well known names checking can be disabled by passing `cfg(any())`
as argument to `--check-cfg`.

Well known names checking is always enable as long as a `--check-cfg` argument is present
**unless** any `cfg(any())` argument is passed.
## Examples

To disable checking of well known names, use this form:
### Equivalence table

```bash
rustc --check-cfg 'cfg(any())'
```
This table describe the equivalence of a `--cfg` argument to a `--check-cfg` argument.

NOTE: If one want to enable values and names checking without having any cfg to declare, one
can use an empty `cfg()` argument.
| `--cfg` | `--check-cfg` |
|-----------------------------|----------------------------------------------------------|
| *nothing* | *nothing* or `--check-cfg=cfg()` (to enable the checking) |
| `--cfg foo` | `--check-cfg=cfg(foo) or --check-cfg=cfg(foo, values())` |
| `--cfg foo=""` | `--check-cfg=cfg(foo, values(""))` |
| `--cfg foo="bar"` | `--check-cfg=cfg(foo, values("bar"))` |
| `--cfg foo="1" --cfg foo="2"` | `--check-cfg=cfg(foo, values("1", "2"))` |
| `--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) --check-cfg=cfg(foo, values("bar"))` |

## Examples
NOTE: There is (currently) no way to express that a condition name is expected but no (!= none)
values are expected. Passing an empty `values()` means *(none)* in the sense of `#[cfg(foo)]`
with no value. Users are expected to NOT pass a `--check-cfg` with that condition name.

### 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"' -Z unstable-options example.rs
```

This command line indicates that this crate has two features: `lion` and `zebra`. The `lion`
feature is enabled, while the `zebra` feature is disabled. Exhaustive checking of names and
values are enabled by default. Consider compiling this code:
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
// This is expected, and tame_lion() will be compiled
#[cfg(feature = "lion")]
#[cfg(feature = "lion")] // This condition is expected, as "lion" is an expected value of `feature`
fn tame_lion(lion: Lion) {}

// This is expected, and ride_zebra() will NOT be compiled.
#[cfg(feature = "zebra")]
fn ride_zebra(zebra: Zebra) {}
#[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
fn ride_zebra(z: Zebra) {}

// This is UNEXPECTED, and will cause a compiler warning (by default).
#[cfg(feature = "platypus")]
#[cfg(feature = "platypus")] // This condition is UNEXPECTED, as "platypus" is NOT an expected value of
// `feature` and will cause a compiler warning (by default).
fn poke_platypus() {}

// This is UNEXPECTED, because 'feechure' is not a known condition name,
// and will cause a compiler warning (by default).
#[cfg(feechure = "lion")]
#[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() {}

// This is UNEXPECTED, because 'windows' is a well known condition name,
// and because 'windows' doesn't take any values,
// and will cause a compiler warning (by default).
#[cfg(windows = "unix")]
#[cfg(windows = "unix")] // This condition is UNEXPECTED, as while 'windows' is a well known
// condition name, it doens't expect any values
fn tame_windows() {}
```

### Example: Checking condition names, but not values
### Example: Multiple names and values

```bash
# This turns on checking for condition names, but not values, such as 'feature' values.
rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \
--cfg has_feathers -Z unstable-options
rustc --check-cfg 'cfg(is_embedded, has_feathers)' \
--check-cfg 'cfg(feature, values("zapping", "lasers"))' \
--cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options
```

```rust
#[cfg(is_embedded)] // This is expected as "is_embedded" was provided in cfg()
fn do_embedded() {} // and because names exhaustiveness was not disabled

#[cfg(has_feathers)] // This is expected as "has_feathers" was provided in cfg()
fn do_features() {} // and because names exhaustiveness was not disabled
#[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(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in cfg()
// and because no value checking was enable for "has_feathers"
// no warning is emitted for the value "zapping"
fn do_zapping() {}
#[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_mumble_frotz)] // This is UNEXPECTED because names checking is enable and
// "has_mumble_frotz" was not provided in cfg()
#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz' was NEVER provided
// in any --check-cfg arguments
fn do_mumble_frotz() {}
```

### Example: Checking feature values, but not condition names

```bash
# This turns on checking for feature values, but not for condition names.
rustc --check-cfg 'cfg(feature, values("zapping", "lasers"))' \
--check-cfg 'cfg(any())' \
--cfg 'feature="zapping"' -Z unstable-options
```

```rust
#[cfg(is_embedded)] // This is doesn't raise a warning, because names checking was
// disabled by 'cfg(any())'
fn do_embedded() {}

#[cfg(has_feathers)] // Same as above, 'cfg(any())' was provided so no name
// checking is performed
fn do_features() {}

#[cfg(feature = "lasers")] // This is expected, "lasers" is in the cfg(feature) list
#[cfg(feature = "lasers")] // This condition is expected, as "lasers" is an expected value of `feature`
fn shoot_lasers() {}

#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in the
// cfg(feature) list
#[cfg(feature = "monkeys")] // This condition is UNEXPECTED, as "monkeys" is NOT an expected value of
// `feature`
fn write_shakespeare() {}
```

### Example: Checking both condition names and feature values
### Example: Condition names without values

```bash
# This turns on checking for feature values and for condition names.
rustc --check-cfg 'cfg(is_embedded, has_feathers)' \
--check-cfg 'cfg(feature, values("zapping", "lasers"))' \
--cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options
rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \
--cfg has_feathers -Z unstable-options
```

```rust
#[cfg(is_embedded)] // This is expected because "is_embedded" was provided in cfg()
fn do_embedded() {} // and doesn't take any value

#[cfg(has_feathers)] // This is expected because "has_feathers" was provided in cfg()
fn do_features() {} // and deosn't take any value
#[cfg(is_embedded)] // This condition is expected, as 'is_embedded' was provided in --check-cfg
// as condition name
fn do_embedded() {}

#[cfg(has_mumble_frotz)] // This is UNEXPECTED, because "has_mumble_frotz" was never provided
fn do_mumble_frotz() {}
#[cfg(has_feathers)] // This condition is expected, as "has_feathers" was provided in --check-cfg
// as condition name
fn do_features() {}

#[cfg(feature = "lasers")] // This is expected, "lasers" is in the cfg(feature) list
fn shoot_lasers() {}
#[cfg(has_feathers = "zapping")] // This condition is expected, as "has_feathers" was provided in
// and because *any* values is expected for 'has_feathers' no
// warning is emitted for the value "zapping"
fn do_zapping() {}

#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in
// the cfg(feature) list
fn write_shakespeare() {}
#[cfg(has_mumble_frotz)] // This condition is UNEXPECTED, as 'has_mumble_frotz' was not provided
// in any --check-cfg arguments
fn do_mumble_frotz() {}
```