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:
commit
69f53f5e55
28 changed files with 151 additions and 34 deletions
|
@ -4162,6 +4162,7 @@ dependencies = [
|
|||
"rustc_ast",
|
||||
"rustc_ast_lowering",
|
||||
"rustc_ast_passes",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr",
|
||||
"rustc_borrowck",
|
||||
"rustc_builtin_macros",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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(...)`");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
6
tests/ui/check-cfg/invalid-arguments.boolean.stderr
Normal file
6
tests/ui/check-cfg/invalid-arguments.boolean.stderr
Normal 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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue