diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 03335996c0354..32fba6ade88df 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -202,8 +202,15 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { if !args.is_empty() { error!("`any()` must be empty"); } + } else if arg.has_name(sym::none) + && let Some(args) = arg.meta_item_list() + { + values.insert(None); + if !args.is_empty() { + error!("`none()` must be empty"); + } } else { - error!("`values()` arguments must be string literals or `any()`"); + error!("`values()` arguments must be string literals, `none()` or `any()`"); } } } else { diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md index e8fc2fe986e22..78bc8dceb7824 100644 --- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md @@ -36,12 +36,16 @@ present in the list of expected values. If `"value"` is not in it, then `rustc` *The command line `--cfg` arguments are currently *NOT* checked but may very well be checked in the future.* +To check for the _none_ value (ie `#[cfg(foo)]`) one can use the `none()` predicate inside +`values()`: `values(none())`. It can be followed or precessed by any number of `"value"`. + 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(name)' rustc --check-cfg 'cfg(name, values())' +rustc --check-cfg 'cfg(name, values(none()))' ``` To enable checking of name but not values (i.e. unknown expected values), use this form: @@ -112,7 +116,7 @@ This table describe the equivalence of a `--cfg` argument to a `--check-cfg` arg | `--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), --check-cfg=cfg(foo, values())` or `--check-cfg=cfg(foo, values(none()))` | | `--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"))` | diff --git a/tests/ui/check-cfg/invalid-arguments.cfg_none.stderr b/tests/ui/check-cfg/invalid-arguments.cfg_none.stderr new file mode 100644 index 0000000000000..7992dbdff005a --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.cfg_none.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(none())` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`) + diff --git a/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr b/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr index 0dc44d9ac76c2..90308bdcd2355 100644 --- a/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr +++ b/tests/ui/check-cfg/invalid-arguments.ident_in_values_1.stderr @@ -1,2 +1,2 @@ -error: invalid `--check-cfg` argument: `cfg(foo,values(bar))` (`values()` arguments must be string literals or `any()`) +error: invalid `--check-cfg` argument: `cfg(foo,values(bar))` (`values()` arguments must be string literals, `none()` or `any()`) diff --git a/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr b/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr index d0a1453e3c406..16f92a504a5fa 100644 --- a/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr +++ b/tests/ui/check-cfg/invalid-arguments.ident_in_values_2.stderr @@ -1,2 +1,2 @@ -error: invalid `--check-cfg` argument: `cfg(foo,values("bar",bar,"bar"))` (`values()` arguments must be string literals or `any()`) +error: invalid `--check-cfg` argument: `cfg(foo,values("bar",bar,"bar"))` (`values()` arguments must be string literals, `none()` or `any()`) diff --git a/tests/ui/check-cfg/invalid-arguments.none_not_empty.stderr b/tests/ui/check-cfg/invalid-arguments.none_not_empty.stderr new file mode 100644 index 0000000000000..0a6c6ffd42f2c --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.none_not_empty.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `cfg(foo,values(none("test")))` (`none()` must be empty) + diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs index 90c62fa38070d..60ba6315558d0 100644 --- a/tests/ui/check-cfg/invalid-arguments.rs +++ b/tests/ui/check-cfg/invalid-arguments.rs @@ -7,6 +7,7 @@ // revisions: values_any_missing_values values_any_before_ident ident_in_values_1 // revisions: ident_in_values_2 unknown_meta_item_1 unknown_meta_item_2 unknown_meta_item_3 // revisions: mixed_values_any mixed_any any_values giberich unterminated +// revisions: none_not_empty cfg_none // // compile-flags: -Z unstable-options // [anything_else]compile-flags: --check-cfg=anything_else(...) @@ -24,9 +25,11 @@ // [unknown_meta_item_1]compile-flags: --check-cfg=abc() // [unknown_meta_item_2]compile-flags: --check-cfg=cfg(foo,test()) // [unknown_meta_item_3]compile-flags: --check-cfg=cfg(foo,values(test())) +// [none_not_empty]compile-flags: --check-cfg=cfg(foo,values(none("test"))) // [mixed_values_any]compile-flags: --check-cfg=cfg(foo,values("bar",any())) // [mixed_any]compile-flags: --check-cfg=cfg(any(),values(any())) // [any_values]compile-flags: --check-cfg=cfg(any(),values()) +// [cfg_none]compile-flags: --check-cfg=cfg(none()) // [giberich]compile-flags: --check-cfg=cfg(...) // [unterminated]compile-flags: --check-cfg=cfg( diff --git a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr index 2441e2537b74f..a023779b35a7b 100644 --- a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr +++ b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_3.stderr @@ -1,2 +1,2 @@ -error: invalid `--check-cfg` argument: `cfg(foo,values(test()))` (`values()` arguments must be string literals or `any()`) +error: invalid `--check-cfg` argument: `cfg(foo,values(test()))` (`values()` arguments must be string literals, `none()` or `any()`) diff --git a/tests/ui/check-cfg/no-expected-values.rs b/tests/ui/check-cfg/no-expected-values.rs index 9f34c019ea534..4f8481315df6b 100644 --- a/tests/ui/check-cfg/no-expected-values.rs +++ b/tests/ui/check-cfg/no-expected-values.rs @@ -6,7 +6,7 @@ // compile-flags: --check-cfg=cfg(values,simple,mixed,empty) // [simple]compile-flags: --check-cfg=cfg(test) --check-cfg=cfg(feature) // [mixed]compile-flags: --check-cfg=cfg(test,feature) -// [empty]compile-flags: --check-cfg=cfg(test,feature,values()) +// [empty]compile-flags: --check-cfg=cfg(test,feature,values(none())) #[cfg(feature = "foo")] //~^ WARNING unexpected `cfg` condition value diff --git a/tests/ui/check-cfg/values-none.explicit.stderr b/tests/ui/check-cfg/values-none.explicit.stderr new file mode 100644 index 0000000000000..a025ff441b708 --- /dev/null +++ b/tests/ui/check-cfg/values-none.explicit.stderr @@ -0,0 +1,27 @@ +warning: unexpected `cfg` condition value: `too` + --> $DIR/values-none.rs:11:7 + | +LL | #[cfg(foo = "too")] + | ^^^-------- + | | + | help: remove the value + | + = note: no expected value for `foo` + = help: to expect this configuration use `--check-cfg=cfg(foo, values("too"))` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `bar` + --> $DIR/values-none.rs:16:7 + | +LL | #[cfg(foo = "bar")] + | ^^^-------- + | | + | help: remove the value + | + = note: no expected value for `foo` + = help: to expect this configuration use `--check-cfg=cfg(foo, values("bar"))` + = note: see for more information about checking conditional configuration + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/values-none.implicit.stderr b/tests/ui/check-cfg/values-none.implicit.stderr new file mode 100644 index 0000000000000..a025ff441b708 --- /dev/null +++ b/tests/ui/check-cfg/values-none.implicit.stderr @@ -0,0 +1,27 @@ +warning: unexpected `cfg` condition value: `too` + --> $DIR/values-none.rs:11:7 + | +LL | #[cfg(foo = "too")] + | ^^^-------- + | | + | help: remove the value + | + = note: no expected value for `foo` + = help: to expect this configuration use `--check-cfg=cfg(foo, values("too"))` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: `bar` + --> $DIR/values-none.rs:16:7 + | +LL | #[cfg(foo = "bar")] + | ^^^-------- + | | + | help: remove the value + | + = note: no expected value for `foo` + = help: to expect this configuration use `--check-cfg=cfg(foo, values("bar"))` + = note: see for more information about checking conditional configuration + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/values-none.rs b/tests/ui/check-cfg/values-none.rs new file mode 100644 index 0000000000000..957ed43a2e236 --- /dev/null +++ b/tests/ui/check-cfg/values-none.rs @@ -0,0 +1,23 @@ +// check-pass +// +// revisions: explicit implicit +// compile-flags: -Zunstable-options +// [explicit]compile-flags: --check-cfg=cfg(foo,values(none())) +// [implicit]compile-flags: --check-cfg=cfg(foo) +// [simple] compile-flags: --check-cfg=cfg(foo,values(none(),"too")) +// [concat_1]compile-flags: --check-cfg=cfg(foo) --check-cfg=cfg(foo,values("too")) +// [concat_2]compile-flags: --check-cfg=cfg(foo,values("too")) --check-cfg=cfg(foo) + +#[cfg(foo = "too")] +//[explicit]~^ WARNING unexpected `cfg` condition value +//[implicit]~^^ WARNING unexpected `cfg` condition value +fn foo_too() {} + +#[cfg(foo = "bar")] +//~^ WARNING unexpected `cfg` condition value +fn foo_bar() {} + +#[cfg(foo)] +fn foo() {} + +fn main() {}