From 228496e4f5f7b94d69ec7e5bc858370ce9540fca Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 3 May 2024 21:14:42 +0200 Subject: [PATCH] Improve check-cfg CLI errors with more structured diagnostics --- Cargo.lock | 1 + compiler/rustc_interface/Cargo.toml | 1 + compiler/rustc_interface/src/interface.rs | 51 +++++++++++++++---- .../invalid-arguments.any_values.stderr | 5 +- .../invalid-arguments.anything_else.stderr | 5 +- .../invalid-arguments.boolean.stderr | 6 +++ .../invalid-arguments.cfg_none.stderr | 6 ++- .../invalid-arguments.giberich.stderr | 5 +- ...invalid-arguments.ident_in_values_1.stderr | 6 ++- ...invalid-arguments.ident_in_values_2.stderr | 6 ++- .../invalid-arguments.mixed_any.stderr | 5 +- .../invalid-arguments.mixed_values_any.stderr | 5 +- .../invalid-arguments.multiple_any.stderr | 5 +- .../invalid-arguments.multiple_values.stderr | 5 +- ...valid-arguments.multiple_values_any.stderr | 6 ++- .../invalid-arguments.none_not_empty.stderr | 6 ++- .../invalid-arguments.not_empty_any.stderr | 6 ++- ...alid-arguments.not_empty_values_any.stderr | 6 ++- tests/ui/check-cfg/invalid-arguments.rs | 3 +- ...invalid-arguments.string_for_name_1.stderr | 6 ++- ...invalid-arguments.string_for_name_2.stderr | 6 ++- ...valid-arguments.unknown_meta_item_1.stderr | 5 +- ...valid-arguments.unknown_meta_item_2.stderr | 6 ++- ...valid-arguments.unknown_meta_item_3.stderr | 6 ++- .../invalid-arguments.unterminated.stderr | 5 +- ...d-arguments.values_any_before_ident.stderr | 5 +- ...arguments.values_any_missing_values.stderr | 5 +- 27 files changed, 150 insertions(+), 33 deletions(-) create mode 100644 tests/ui/check-cfg/invalid-arguments.boolean.stderr diff --git a/Cargo.lock b/Cargo.lock index e5b5543b367..84f7d21239a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4162,6 +4162,7 @@ dependencies = [ "rustc_ast", "rustc_ast_lowering", "rustc_ast_passes", + "rustc_ast_pretty", "rustc_attr", "rustc_borrowck", "rustc_builtin_macros", diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 0e90836145e..4b3b0728f38 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -10,6 +10,7 @@ rustc-rayon-core = { version = "0.5.0", optional = true } rustc_ast = { path = "../rustc_ast" } rustc_ast_lowering = { path = "../rustc_ast_lowering" } rustc_ast_passes = { path = "../rustc_ast_passes" } +rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_attr = { path = "../rustc_attr" } rustc_borrowck = { path = "../rustc_borrowck" } rustc_builtin_macros = { path = "../rustc_builtin_macros" } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index c5b81dbd679..55304bbbd92 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -120,14 +120,45 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { ); let filename = FileName::cfg_spec_source_code(&s); + const VISIT: &str = + "visit for more details"; + macro_rules! error { ($reason:expr) => { #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] - dcx.fatal(format!( - concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), - s - )) + { + let mut diag = + dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`")); + diag.note($reason); + diag.note(VISIT); + diag.emit() + } + }; + (in $arg:expr, $reason:expr) => { + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + { + let mut diag = + dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`")); + + let pparg = rustc_ast_pretty::pprust::meta_list_item_to_string($arg); + if let Some(lit) = $arg.lit() { + let (lit_kind_article, lit_kind_descr) = { + let lit_kind = lit.as_token_lit().kind; + (lit_kind.article(), lit_kind.descr()) + }; + diag.note(format!( + "`{pparg}` is {lit_kind_article} {lit_kind_descr} literal" + )); + } else { + diag.note(format!("`{pparg}` is invalid")); + } + + diag.note($reason); + diag.note(VISIT); + diag.emit() + } }; } @@ -183,7 +214,7 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { } any_specified = true; if !args.is_empty() { - error!("`any()` must be empty"); + error!(in arg, "`any()` takes no argument"); } } else if arg.has_name(sym::values) && let Some(args) = arg.meta_item_list() @@ -202,25 +233,25 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { && let Some(args) = arg.meta_item_list() { if values_any_specified { - error!("`any()` in `values()` cannot be specified multiple times"); + error!(in arg, "`any()` in `values()` cannot be specified multiple times"); } values_any_specified = true; if !args.is_empty() { - error!("`any()` must be empty"); + error!(in arg, "`any()` in `values()` takes no argument"); } } 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"); + error!(in arg, "`none()` in `values()` takes no argument"); } } else { - error!("`values()` arguments must be string literals, `none()` or `any()`"); + error!(in arg, "`values()` arguments must be string literals, `none()` or `any()`"); } } } else { - error!("`cfg()` arguments must be simple identifiers, `any()` or `values(...)`"); + error!(in arg, "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`"); } } diff --git a/tests/ui/check-cfg/invalid-arguments.any_values.stderr b/tests/ui/check-cfg/invalid-arguments.any_values.stderr index f9a9c4a6e13..65ef5155fa1 100644 --- a/tests/ui/check-cfg/invalid-arguments.any_values.stderr +++ b/tests/ui/check-cfg/invalid-arguments.any_values.stderr @@ -1,2 +1,5 @@ -error: invalid `--check-cfg` argument: `cfg(any(),values())` (`values()` cannot be specified before the names) +error: invalid `--check-cfg` argument: `cfg(any(),values())` + | + = note: `values()` cannot be specified before the names + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.anything_else.stderr b/tests/ui/check-cfg/invalid-arguments.anything_else.stderr index 925664bb3fc..f3bc0b782e2 100644 --- a/tests/ui/check-cfg/invalid-arguments.anything_else.stderr +++ b/tests/ui/check-cfg/invalid-arguments.anything_else.stderr @@ -1,2 +1,5 @@ -error: invalid `--check-cfg` argument: `anything_else(...)` (expected `cfg(name, values("value1", "value2", ... "valueN"))`) +error: invalid `--check-cfg` argument: `anything_else(...)` + | + = note: expected `cfg(name, values("value1", "value2", ... "valueN"))` + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.boolean.stderr b/tests/ui/check-cfg/invalid-arguments.boolean.stderr new file mode 100644 index 00000000000..18734de9dac --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.boolean.stderr @@ -0,0 +1,6 @@ +error: invalid `--check-cfg` argument: `cfg(true)` + | + = note: `true` is a boolean literal + = note: `cfg()` arguments must be simple identifiers, `any()` or `values(...)` + = note: visit for more details + diff --git a/tests/ui/check-cfg/invalid-arguments.cfg_none.stderr b/tests/ui/check-cfg/invalid-arguments.cfg_none.stderr index 7992dbdff00..ef464260c29 100644 --- a/tests/ui/check-cfg/invalid-arguments.cfg_none.stderr +++ b/tests/ui/check-cfg/invalid-arguments.cfg_none.stderr @@ -1,2 +1,6 @@ -error: invalid `--check-cfg` argument: `cfg(none())` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`) +error: invalid `--check-cfg` argument: `cfg(none())` + | + = note: `none()` is invalid + = note: `cfg()` arguments must be simple identifiers, `any()` or `values(...)` + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.giberich.stderr b/tests/ui/check-cfg/invalid-arguments.giberich.stderr index d427033fcc2..3e350145491 100644 --- a/tests/ui/check-cfg/invalid-arguments.giberich.stderr +++ b/tests/ui/check-cfg/invalid-arguments.giberich.stderr @@ -1,2 +1,5 @@ -error: invalid `--check-cfg` argument: `cfg(...)` (expected `cfg(name, values("value1", "value2", ... "valueN"))`) +error: invalid `--check-cfg` argument: `cfg(...)` + | + = note: expected `cfg(name, values("value1", "value2", ... "valueN"))` + = note: visit for more details 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 90308bdcd23..cfedb7ed517 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,6 @@ -error: invalid `--check-cfg` argument: `cfg(foo,values(bar))` (`values()` arguments must be string literals, `none()` or `any()`) +error: invalid `--check-cfg` argument: `cfg(foo,values(bar))` + | + = note: `bar` is invalid + = note: `values()` arguments must be string literals, `none()` or `any()` + = note: visit for more details 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 16f92a504a5..ba194862284 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,6 @@ -error: invalid `--check-cfg` argument: `cfg(foo,values("bar",bar,"bar"))` (`values()` arguments must be string literals, `none()` or `any()`) +error: invalid `--check-cfg` argument: `cfg(foo,values("bar",bar,"bar"))` + | + = note: `bar` is invalid + = note: `values()` arguments must be string literals, `none()` or `any()` + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr b/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr index 9239f8cce94..512ecbe9eda 100644 --- a/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr +++ b/tests/ui/check-cfg/invalid-arguments.mixed_any.stderr @@ -1,2 +1,5 @@ -error: invalid `--check-cfg` argument: `cfg(any(),values(any()))` (`values()` cannot be specified before the names) +error: invalid `--check-cfg` argument: `cfg(any(),values(any()))` + | + = note: `values()` cannot be specified before the names + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr b/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr index 4c406143d08..2d59b12097d 100644 --- a/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr +++ b/tests/ui/check-cfg/invalid-arguments.mixed_values_any.stderr @@ -1,2 +1,5 @@ -error: invalid `--check-cfg` argument: `cfg(foo,values("bar",any()))` (`values()` arguments cannot specify string literals and `any()` at the same time) +error: invalid `--check-cfg` argument: `cfg(foo,values("bar",any()))` + | + = note: `values()` arguments cannot specify string literals and `any()` at the same time + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr b/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr index 6f1db1b13c3..6eb63de4252 100644 --- a/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr +++ b/tests/ui/check-cfg/invalid-arguments.multiple_any.stderr @@ -1,2 +1,5 @@ -error: invalid `--check-cfg` argument: `cfg(any(),any())` (`any()` cannot be specified multiple times) +error: invalid `--check-cfg` argument: `cfg(any(),any())` + | + = note: `any()` cannot be specified multiple times + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr b/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr index bce305b09c3..06060078bc0 100644 --- a/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr +++ b/tests/ui/check-cfg/invalid-arguments.multiple_values.stderr @@ -1,2 +1,5 @@ -error: invalid `--check-cfg` argument: `cfg(foo,values(),values())` (`values()` cannot be specified multiple times) +error: invalid `--check-cfg` argument: `cfg(foo,values(),values())` + | + = note: `values()` cannot be specified multiple times + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr b/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr index 748ce231af7..72554ac3ead 100644 --- a/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr +++ b/tests/ui/check-cfg/invalid-arguments.multiple_values_any.stderr @@ -1,2 +1,6 @@ -error: invalid `--check-cfg` argument: `cfg(foo,values(any(),any()))` (`any()` in `values()` cannot be specified multiple times) +error: invalid `--check-cfg` argument: `cfg(foo,values(any(),any()))` + | + = note: `any()` is invalid + = note: `any()` in `values()` cannot be specified multiple times + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.none_not_empty.stderr b/tests/ui/check-cfg/invalid-arguments.none_not_empty.stderr index 0a6c6ffd42f..6e9d87bace2 100644 --- a/tests/ui/check-cfg/invalid-arguments.none_not_empty.stderr +++ b/tests/ui/check-cfg/invalid-arguments.none_not_empty.stderr @@ -1,2 +1,6 @@ -error: invalid `--check-cfg` argument: `cfg(foo,values(none("test")))` (`none()` must be empty) +error: invalid `--check-cfg` argument: `cfg(foo,values(none("test")))` + | + = note: `none("test")` is invalid + = note: `none()` in `values()` takes no argument + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr b/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr index daf38147fe5..35eb1949ad7 100644 --- a/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr +++ b/tests/ui/check-cfg/invalid-arguments.not_empty_any.stderr @@ -1,2 +1,6 @@ -error: invalid `--check-cfg` argument: `cfg(any(foo))` (`any()` must be empty) +error: invalid `--check-cfg` argument: `cfg(any(foo))` + | + = note: `any(foo)` is invalid + = note: `any()` takes no argument + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr b/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr index 79f83e802ca..cc41d21bec6 100644 --- a/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr +++ b/tests/ui/check-cfg/invalid-arguments.not_empty_values_any.stderr @@ -1,2 +1,6 @@ -error: invalid `--check-cfg` argument: `cfg(foo,values(any(bar)))` (`any()` must be empty) +error: invalid `--check-cfg` argument: `cfg(foo,values(any(bar)))` + | + = note: `any(bar)` is invalid + = note: `any()` in `values()` takes no argument + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs index c0b58ede97f..b8588ecb4ff 100644 --- a/tests/ui/check-cfg/invalid-arguments.rs +++ b/tests/ui/check-cfg/invalid-arguments.rs @@ -2,7 +2,7 @@ // //@ check-fail //@ no-auto-check-cfg -//@ revisions: anything_else +//@ revisions: anything_else boolean //@ revisions: string_for_name_1 string_for_name_2 multiple_any multiple_values //@ revisions: multiple_values_any not_empty_any not_empty_values_any //@ revisions: values_any_missing_values values_any_before_ident ident_in_values_1 @@ -11,6 +11,7 @@ //@ revisions: none_not_empty cfg_none // //@ [anything_else]compile-flags: --check-cfg=anything_else(...) +//@ [boolean]compile-flags: --check-cfg=cfg(true) //@ [string_for_name_1]compile-flags: --check-cfg=cfg("NOT_IDENT") //@ [string_for_name_2]compile-flags: --check-cfg=cfg(foo,"NOT_IDENT",bar) //@ [multiple_any]compile-flags: --check-cfg=cfg(any(),any()) diff --git a/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr b/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr index c6f6834ffd3..7022b709b64 100644 --- a/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr +++ b/tests/ui/check-cfg/invalid-arguments.string_for_name_1.stderr @@ -1,2 +1,6 @@ -error: invalid `--check-cfg` argument: `cfg("NOT_IDENT")` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`) +error: invalid `--check-cfg` argument: `cfg("NOT_IDENT")` + | + = note: `"NOT_IDENT"` is a string literal + = note: `cfg()` arguments must be simple identifiers, `any()` or `values(...)` + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr b/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr index ab3dc86cd1a..ea96b913907 100644 --- a/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr +++ b/tests/ui/check-cfg/invalid-arguments.string_for_name_2.stderr @@ -1,2 +1,6 @@ -error: invalid `--check-cfg` argument: `cfg(foo,"NOT_IDENT",bar)` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`) +error: invalid `--check-cfg` argument: `cfg(foo,"NOT_IDENT",bar)` + | + = note: `"NOT_IDENT"` is a string literal + = note: `cfg()` arguments must be simple identifiers, `any()` or `values(...)` + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr index c04b15ec265..f82c520c62a 100644 --- a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr +++ b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_1.stderr @@ -1,2 +1,5 @@ -error: invalid `--check-cfg` argument: `abc()` (expected `cfg(name, values("value1", "value2", ... "valueN"))`) +error: invalid `--check-cfg` argument: `abc()` + | + = note: expected `cfg(name, values("value1", "value2", ... "valueN"))` + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr index cee65f9887b..ee62c25b41c 100644 --- a/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr +++ b/tests/ui/check-cfg/invalid-arguments.unknown_meta_item_2.stderr @@ -1,2 +1,6 @@ -error: invalid `--check-cfg` argument: `cfg(foo,test())` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`) +error: invalid `--check-cfg` argument: `cfg(foo,test())` + | + = note: `test()` is invalid + = note: `cfg()` arguments must be simple identifiers, `any()` or `values(...)` + = note: visit for more details 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 a023779b35a..a8ab9cc9d30 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,6 @@ -error: invalid `--check-cfg` argument: `cfg(foo,values(test()))` (`values()` arguments must be string literals, `none()` or `any()`) +error: invalid `--check-cfg` argument: `cfg(foo,values(test()))` + | + = note: `test()` is invalid + = note: `values()` arguments must be string literals, `none()` or `any()` + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.unterminated.stderr b/tests/ui/check-cfg/invalid-arguments.unterminated.stderr index 80161a6aa0f..150e1d66426 100644 --- a/tests/ui/check-cfg/invalid-arguments.unterminated.stderr +++ b/tests/ui/check-cfg/invalid-arguments.unterminated.stderr @@ -1,2 +1,5 @@ -error: invalid `--check-cfg` argument: `cfg(` (expected `cfg(name, values("value1", "value2", ... "valueN"))`) +error: invalid `--check-cfg` argument: `cfg(` + | + = note: expected `cfg(name, values("value1", "value2", ... "valueN"))` + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr b/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr index fc93ec8fbdf..7013bb8e095 100644 --- a/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr +++ b/tests/ui/check-cfg/invalid-arguments.values_any_before_ident.stderr @@ -1,2 +1,5 @@ -error: invalid `--check-cfg` argument: `cfg(values(any()),foo)` (`values()` cannot be specified before the names) +error: invalid `--check-cfg` argument: `cfg(values(any()),foo)` + | + = note: `values()` cannot be specified before the names + = note: visit for more details diff --git a/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr b/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr index f41672fcbdb..ad1af73c690 100644 --- a/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr +++ b/tests/ui/check-cfg/invalid-arguments.values_any_missing_values.stderr @@ -1,2 +1,5 @@ -error: invalid `--check-cfg` argument: `cfg(foo,any())` (`cfg(any())` can only be provided in isolation) +error: invalid `--check-cfg` argument: `cfg(foo,any())` + | + = note: `cfg(any())` can only be provided in isolation + = note: visit for more details