Auto merge of #124679 - Urgau:check-cfg-structured-cli-errors, r=nnethercote

Improve check-cfg CLI errors with more structured diagnostics

This PR improve check-cfg CLI errors with more structured diagnostics.

In particular it now shows the statement where the error occurred, what kind lit it is, as well as pointing users to the doc for more details.

`@rustbot` label +F-check-cfg
This commit is contained in:
bors 2024-05-06 07:46:27 +00:00
commit 69f53f5e55
28 changed files with 151 additions and 34 deletions

View file

@ -4162,6 +4162,7 @@ dependencies = [
"rustc_ast",
"rustc_ast_lowering",
"rustc_ast_passes",
"rustc_ast_pretty",
"rustc_attr",
"rustc_borrowck",
"rustc_builtin_macros",

View file

@ -167,7 +167,7 @@ impl LitKind {
pub fn descr(self) -> &'static str {
match self {
Bool => panic!("literal token contains `Lit::Bool`"),
Bool => "boolean",
Byte => "byte",
Char => "char",
Integer => "integer",

View file

@ -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" }

View file

@ -120,14 +120,45 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
);
let filename = FileName::cfg_spec_source_code(&s);
const VISIT: &str =
"visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> 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<String>) -> 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<String>) -> 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(...)`");
}
}

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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())

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details

View file

@ -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 <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details