Skip to content

Commit c58a5da

Browse files
committed
Auto merge of rust-lang#119930 - Urgau:check-cfg-empty-values-means-empty, r=petrochenkov
Add way to express that no values are expected with check-cfg This PR adds way to express no-values (no values expected) with `--check-cfg` by making empty `values()` no longer mean `values(none())` (internal: `&[None]`) and now be an empty list (internal: `&[]`). ### Context Currently `--check-cfg` has a way to express that _any value is expected_ with `values(any())`, but has no way to do the inverse and say that _no value is expected_. This would be particularly useful for build systems that control a config name and it's values as they could always declare a config name as expected and if in the current state they have values pass them and if not pass an empty list. To give a more concrete example, Cargo `--check-cfg` currently needs to generate: - `--check-cfg=cfg(feature, values(...))` for the case with declared features - and `--check-cfg=cfg()` for the case without any features declared This means that when there are no features declared, users will get an `unexpected config name` but from the point of view of Cargo the config name `feature` is expected, it's just that for now there aren't any values for it. See [Cargo `check_cfg_args` function](https://github.com/rust-lang/cargo/blob/92395d90106b3b61bcb68bcf2069052c93771764/src/cargo/core/compiler/mod.rs#L1263-L1281) for more details. ### De-specializing *empty* `values()` To solve this issue I propose that we "de-specialize" empty `values()` to no longer mean `values(none())` but to actually mean empty set/list. This is one of the last source of confusion for my-self and others with the `--check-cfg` syntax. > The confusing part here is that an empty `values()` currently means the same as `values(none())`, i.e. an expected list of values with the _none_ variant (as in `#[cfg(name)]` where the value is none) instead of meaning an empty set. Before the new `cfg()` syntax, defining the _none_ variant was only possible under certain circumstances, so in rust-lang#111068 I decided to make `values()` to mean the _none_ variant, but it is no longer necessary since rust-lang#119473 which introduced the `none()` syntax. A simplified representation of the proposed "de-specialization" would be: | Syntax | List/set of expected values | |-----------------------------------------|-----------------------------| | `cfg(name)`/`cfg(name, values(none()))` | `&[None]` | | `cfg(name, values())` | `&[]` | Note that I have my-self made the mistake of using an empty `values()` as meaning empty set, see rust-lang/cargo#13011. `@rustbot` label +F-check-cfg r? `@petrochenkov` cc `@epage`
2 parents 52790a9 + 41b69aa commit c58a5da

File tree

10 files changed

+89
-32
lines changed

10 files changed

+89
-32
lines changed

compiler/rustc_interface/src/interface.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,9 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
218218
}
219219
}
220220

221-
if values.is_empty() && !values_any_specified && !any_specified {
221+
if !values_specified && !any_specified {
222+
// `cfg(name)` is equivalent to `cfg(name, values(none()))` so add
223+
// an implicit `none()`
222224
values.insert(None);
223225
} else if !values.is_empty() && values_any_specified {
224226
error!(

compiler/rustc_lint/src/context/diagnostics.rs

+11
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,15 @@ pub(super) fn builtin(
354354
Applicability::MaybeIncorrect,
355355
);
356356
}
357+
} else {
358+
db.note(format!("no expected values for `{name}`"));
359+
360+
let sp = if let Some((_value, value_span)) = value {
361+
name_span.to(value_span)
362+
} else {
363+
name_span
364+
};
365+
db.span_suggestion(sp, "remove the condition", "", Applicability::MaybeIncorrect);
357366
}
358367

359368
// We don't want to suggest adding values to well known names
@@ -373,6 +382,8 @@ pub(super) fn builtin(
373382
if name == sym::feature {
374383
if let Some((value, _value_span)) = value {
375384
db.help(format!("consider adding `{value}` as a feature in `Cargo.toml`"));
385+
} else {
386+
db.help("consider defining some features in `Cargo.toml`");
376387
}
377388
} else if !is_cfg_a_well_know_name {
378389
db.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));

src/doc/unstable-book/src/compiler-flags/check-cfg.md

+13-12
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,20 @@ To enable checking of values, but to provide an *none*/empty set of expected val
4444

4545
```bash
4646
rustc --check-cfg 'cfg(name)'
47-
rustc --check-cfg 'cfg(name, values())'
4847
rustc --check-cfg 'cfg(name, values(none()))'
4948
```
5049

51-
To enable checking of name but not values (i.e. unknown expected values), use this form:
50+
To enable checking of name but not values, use one of these forms:
5251

53-
```bash
54-
rustc --check-cfg 'cfg(name, values(any()))'
55-
```
52+
- No expected values (_will lint on every value_):
53+
```bash
54+
rustc --check-cfg 'cfg(name, values())'
55+
```
56+
57+
- Unknown expected values (_will never lint_):
58+
```bash
59+
rustc --check-cfg 'cfg(name, values(any()))'
60+
```
5661

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

@@ -114,18 +119,14 @@ as argument to `--check-cfg`.
114119
This table describe the equivalence of a `--cfg` argument to a `--check-cfg` argument.
115120
116121
| `--cfg` | `--check-cfg` |
117-
|-----------------------------|----------------------------------------------------------|
122+
|-------------------------------|------------------------------------------------------------|
118123
| *nothing* | *nothing* or `--check-cfg=cfg()` (to enable the checking) |
119-
| `--cfg foo` | `--check-cfg=cfg(foo), --check-cfg=cfg(foo, values())` or `--check-cfg=cfg(foo, values(none()))` |
124+
| `--cfg foo` | `--check-cfg=cfg(foo)` or `--check-cfg=cfg(foo, values(none()))` |
120125
| `--cfg foo=""` | `--check-cfg=cfg(foo, values(""))` |
121126
| `--cfg foo="bar"` | `--check-cfg=cfg(foo, values("bar"))` |
122127
| `--cfg foo="1" --cfg foo="2"` | `--check-cfg=cfg(foo, values("1", "2"))` |
123128
| `--cfg foo="1" --cfg bar="2"` | `--check-cfg=cfg(foo, values("1")) --check-cfg=cfg(bar, values("2"))` |
124-
| `--cfg foo --cfg foo="bar"` | `--check-cfg=cfg(foo) --check-cfg=cfg(foo, values("bar"))` |
125-
126-
NOTE: There is (currently) no way to express that a condition name is expected but no (!= none)
127-
values are expected. Passing an empty `values()` means *(none)* in the sense of `#[cfg(foo)]`
128-
with no value. Users are expected to NOT pass a `--check-cfg` with that condition name.
129+
| `--cfg foo --cfg foo="bar"` | `--check-cfg=cfg(foo, values(none(), "bar"))` |
129130
130131
### Example: Cargo-like `feature` example
131132

tests/ui/check-cfg/cargo-feature.none.stderr

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,36 @@
1-
warning: unexpected `cfg` condition name: `feature`
2-
--> $DIR/cargo-feature.rs:13:7
1+
warning: unexpected `cfg` condition value: `serde`
2+
--> $DIR/cargo-feature.rs:14:7
33
|
44
LL | #[cfg(feature = "serde")]
5-
| ^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^ help: remove the condition
66
|
7-
= help: consider defining some features in `Cargo.toml`
7+
= note: no expected values for `feature`
8+
= help: consider adding `serde` as a feature in `Cargo.toml`
89
= note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
910
= note: `#[warn(unexpected_cfgs)]` on by default
1011

11-
warning: unexpected `cfg` condition name: `feature`
12+
warning: unexpected `cfg` condition value: (none)
1213
--> $DIR/cargo-feature.rs:18:7
1314
|
1415
LL | #[cfg(feature)]
15-
| ^^^^^^^
16+
| ^^^^^^^ help: remove the condition
1617
|
18+
= note: no expected values for `feature`
1719
= help: consider defining some features in `Cargo.toml`
1820
= note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
1921

2022
warning: unexpected `cfg` condition name: `tokio_unstable`
21-
--> $DIR/cargo-feature.rs:23:7
23+
--> $DIR/cargo-feature.rs:22:7
2224
|
2325
LL | #[cfg(tokio_unstable)]
2426
| ^^^^^^^^^^^^^^
2527
|
26-
= help: expected names are: `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`
28+
= help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `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`
2729
= help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(tokio_unstable)");` to the top of a `build.rs`
2830
= note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
2931

3032
warning: unexpected `cfg` condition name: `CONFIG_NVME`
31-
--> $DIR/cargo-feature.rs:27:7
33+
--> $DIR/cargo-feature.rs:26:7
3234
|
3335
LL | #[cfg(CONFIG_NVME = "m")]
3436
| ^^^^^^^^^^^^^^^^^

tests/ui/check-cfg/cargo-feature.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,18 @@
55
// check-pass
66
// revisions: some none
77
// rustc-env:CARGO=/usr/bin/cargo
8-
// compile-flags: --check-cfg=cfg() -Z unstable-options
8+
// compile-flags: -Z unstable-options
9+
// [none]compile-flags: --check-cfg=cfg(feature,values())
910
// [some]compile-flags: --check-cfg=cfg(feature,values("bitcode"))
1011
// [some]compile-flags: --check-cfg=cfg(CONFIG_NVME,values("y"))
1112
// [none]error-pattern:Cargo.toml
1213

1314
#[cfg(feature = "serde")]
14-
//[none]~^ WARNING unexpected `cfg` condition name
15-
//[some]~^^ WARNING unexpected `cfg` condition value
15+
//~^ WARNING unexpected `cfg` condition value
1616
fn ser() {}
1717

1818
#[cfg(feature)]
19-
//[none]~^ WARNING unexpected `cfg` condition name
20-
//[some]~^^ WARNING unexpected `cfg` condition value
19+
//~^ WARNING unexpected `cfg` condition value
2120
fn feat() {}
2221

2322
#[cfg(tokio_unstable)]

tests/ui/check-cfg/cargo-feature.some.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: unexpected `cfg` condition value: `serde`
2-
--> $DIR/cargo-feature.rs:13:7
2+
--> $DIR/cargo-feature.rs:14:7
33
|
44
LL | #[cfg(feature = "serde")]
55
| ^^^^^^^^^^^^^^^^^
@@ -16,10 +16,11 @@ LL | #[cfg(feature)]
1616
| ^^^^^^^- help: specify a config value: `= "bitcode"`
1717
|
1818
= note: expected values for `feature` are: `bitcode`
19+
= help: consider defining some features in `Cargo.toml`
1920
= note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
2021

2122
warning: unexpected `cfg` condition name: `tokio_unstable`
22-
--> $DIR/cargo-feature.rs:23:7
23+
--> $DIR/cargo-feature.rs:22:7
2324
|
2425
LL | #[cfg(tokio_unstable)]
2526
| ^^^^^^^^^^^^^^
@@ -29,7 +30,7 @@ LL | #[cfg(tokio_unstable)]
2930
= note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
3031

3132
warning: unexpected `cfg` condition value: `m`
32-
--> $DIR/cargo-feature.rs:27:7
33+
--> $DIR/cargo-feature.rs:26:7
3334
|
3435
LL | #[cfg(CONFIG_NVME = "m")]
3536
| ^^^^^^^^^^^^^^---

tests/ui/check-cfg/concat-values.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// check-pass
22
// compile-flags: -Z unstable-options
33
// compile-flags: --check-cfg=cfg(my_cfg,values("foo")) --check-cfg=cfg(my_cfg,values("bar"))
4+
// compile-flags: --check-cfg=cfg(my_cfg,values())
45

56
#[cfg(my_cfg)]
67
//~^ WARNING unexpected `cfg` condition value
@@ -10,4 +11,7 @@ fn my_cfg() {}
1011
//~^ WARNING unexpected `cfg` condition value
1112
fn my_cfg() {}
1213

14+
#[cfg(any(my_cfg = "foo", my_cfg = "bar"))]
15+
fn foo_and_bar() {}
16+
1317
fn main() {}

tests/ui/check-cfg/concat-values.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: unexpected `cfg` condition value: (none)
2-
--> $DIR/concat-values.rs:5:7
2+
--> $DIR/concat-values.rs:6:7
33
|
44
LL | #[cfg(my_cfg)]
55
| ^^^^^^
@@ -10,7 +10,7 @@ LL | #[cfg(my_cfg)]
1010
= note: `#[warn(unexpected_cfgs)]` on by default
1111

1212
warning: unexpected `cfg` condition value: `unk`
13-
--> $DIR/concat-values.rs:9:7
13+
--> $DIR/concat-values.rs:10:7
1414
|
1515
LL | #[cfg(my_cfg = "unk")]
1616
| ^^^^^^^^^^^^^^

tests/ui/check-cfg/empty-values.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Check that we detect unexpected value when none are allowed
2+
//
3+
// check-pass
4+
// compile-flags: --check-cfg=cfg(foo,values()) -Zunstable-options
5+
6+
#[cfg(foo = "foo")]
7+
//~^ WARNING unexpected `cfg` condition value
8+
fn do_foo() {}
9+
10+
#[cfg(foo)]
11+
//~^ WARNING unexpected `cfg` condition value
12+
fn do_foo() {}
13+
14+
fn main() {}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
warning: unexpected `cfg` condition value: `foo`
2+
--> $DIR/empty-values.rs:6:7
3+
|
4+
LL | #[cfg(foo = "foo")]
5+
| ^^^^^^^^^^^ help: remove the condition
6+
|
7+
= note: no expected values for `foo`
8+
= help: to expect this configuration use `--check-cfg=cfg(foo, values("foo"))`
9+
= note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
10+
= note: `#[warn(unexpected_cfgs)]` on by default
11+
12+
warning: unexpected `cfg` condition value: (none)
13+
--> $DIR/empty-values.rs:10:7
14+
|
15+
LL | #[cfg(foo)]
16+
| ^^^ help: remove the condition
17+
|
18+
= note: no expected values for `foo`
19+
= help: to expect this configuration use `--check-cfg=cfg(foo)`
20+
= note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
21+
22+
warning: 2 warnings emitted
23+

0 commit comments

Comments
 (0)