1
Fork 0

Rollup merge of #117025 - Urgau:cleanup-improve-check-cfg-impl, r=petrochenkov

Cleanup and improve `--check-cfg` implementation

This PR removes some indentation in the code, as well as preventing some bugs/misusages and fix a nit in the doc.

r? ```@petrochenkov``` (maybe)
This commit is contained in:
Jubilee 2023-10-28 01:07:37 -07:00 committed by GitHub
commit 87a564d271
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 201 additions and 210 deletions

View file

@ -148,13 +148,28 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
}; };
} }
let expected_error = let expected_error = || -> ! {
|| error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`"); error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`")
};
let Ok(mut parser) = maybe_new_parser_from_source_str(&sess, filename, s.to_string())
else {
expected_error();
};
let meta_item = match parser.parse_meta_item() {
Ok(meta_item) if parser.token == token::Eof => meta_item,
Ok(..) => expected_error(),
Err(err) => {
err.cancel();
expected_error();
}
};
let Some(args) = meta_item.meta_item_list() else {
expected_error();
};
match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) {
Ok(mut parser) => match parser.parse_meta_item() {
Ok(meta_item) if parser.token == token::Eof => {
if let Some(args) = meta_item.meta_item_list() {
if meta_item.has_name(sym::names) { if meta_item.has_name(sym::names) {
// defaults are flipped for the old syntax // defaults are flipped for the old syntax
if old_syntax == None { if old_syntax == None {
@ -194,28 +209,20 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
ExpectedValues::Any => { ExpectedValues::Any => {
// handle the case where names(...) was done // handle the case where names(...) was done
// before values by changing to a list // before values by changing to a list
*expected_values = *expected_values = ExpectedValues::Some(FxHashSet::default());
ExpectedValues::Some(FxHashSet::default());
} }
}) })
.or_insert_with(|| { .or_insert_with(|| ExpectedValues::Some(FxHashSet::default()));
ExpectedValues::Some(FxHashSet::default())
});
let ExpectedValues::Some(expected_values) = expected_values let ExpectedValues::Some(expected_values) = expected_values else {
else {
bug!("`expected_values` should be a list a values") bug!("`expected_values` should be a list a values")
}; };
for val in values { for val in values {
if let Some(LitKind::Str(s, _)) = if let Some(LitKind::Str(s, _)) = val.lit().map(|lit| &lit.kind) {
val.lit().map(|lit| &lit.kind)
{
expected_values.insert(Some(s.to_string())); expected_values.insert(Some(s.to_string()));
} else { } else {
error!( error!("`values()` arguments must be string literals");
"`values()` arguments must be string literals"
);
} }
} }
@ -223,9 +230,7 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
expected_values.insert(None); expected_values.insert(None);
} }
} else { } else {
error!( error!("`values()` first argument must be a simple identifier");
"`values()` first argument must be a simple identifier"
);
} }
} else if args.is_empty() { } else if args.is_empty() {
check_cfg.exhaustive_values = true; check_cfg.exhaustive_values = true;
@ -262,13 +267,9 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
&& let Some(args) = arg.meta_item_list() && let Some(args) = arg.meta_item_list()
{ {
if names.is_empty() { if names.is_empty() {
error!( error!("`values()` cannot be specified before the names");
"`values()` cannot be specified before the names"
);
} else if values_specified { } else if values_specified {
error!( error!("`values()` cannot be specified multiple times");
"`values()` cannot be specified multiple times"
);
} }
values_specified = true; values_specified = true;
@ -311,23 +312,22 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
} }
if any_specified { if any_specified {
if !names.is_empty() if names.is_empty()
|| !values.is_empty() && values.is_empty()
|| values_any_specified && !values_specified
&& !values_any_specified
{ {
check_cfg.exhaustive_names = false;
} else {
error!("`cfg(any())` can only be provided in isolation"); error!("`cfg(any())` can only be provided in isolation");
} }
check_cfg.exhaustive_names = false;
} else { } else {
for name in names { for name in names {
check_cfg check_cfg
.expecteds .expecteds
.entry(name.to_string()) .entry(name.to_string())
.and_modify(|v| match v { .and_modify(|v| match v {
ExpectedValues::Some(v) ExpectedValues::Some(v) if !values_any_specified => {
if !values_any_specified =>
{
v.extend(values.clone()) v.extend(values.clone())
} }
ExpectedValues::Some(_) => *v = ExpectedValues::Any, ExpectedValues::Some(_) => *v = ExpectedValues::Any,
@ -345,21 +345,6 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
} else { } else {
expected_error(); expected_error();
} }
} else {
expected_error();
}
}
Ok(..) => expected_error(),
Err(err) => {
err.cancel();
expected_error();
}
},
Err(errs) => {
drop(errs);
expected_error();
}
}
} }
check_cfg check_cfg

View file

@ -139,7 +139,7 @@ fn do_mumble_frotz() {}
```bash ```bash
# This turns on checking for feature values, but not for condition names. # This turns on checking for feature values, but not for condition names.
rustc --check-cfg 'configure(feature, values("zapping", "lasers"))' \ rustc --check-cfg 'cfg(feature, values("zapping", "lasers"))' \
--check-cfg 'cfg(any())' \ --check-cfg 'cfg(any())' \
--cfg 'feature="zapping"' -Z unstable-options --cfg 'feature="zapping"' -Z unstable-options
``` ```

View file

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(any(),values())` (`values()` cannot be specified before the names)

View file

@ -6,7 +6,7 @@
// revisions: multiple_values_any not_empty_any not_empty_values_any // revisions: multiple_values_any not_empty_any not_empty_values_any
// revisions: values_any_missing_values values_any_before_ident ident_in_values_1 // 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: ident_in_values_2 unknown_meta_item_1 unknown_meta_item_2 unknown_meta_item_3
// revisions: mixed_values_any mixed_any giberich // revisions: mixed_values_any mixed_any any_values giberich unterminated
// //
// compile-flags: -Z unstable-options // compile-flags: -Z unstable-options
// [anything_else]compile-flags: --check-cfg=anything_else(...) // [anything_else]compile-flags: --check-cfg=anything_else(...)
@ -29,6 +29,8 @@
// [unknown_meta_item_3]compile-flags: --check-cfg=cfg(foo,values(test())) // [unknown_meta_item_3]compile-flags: --check-cfg=cfg(foo,values(test()))
// [mixed_values_any]compile-flags: --check-cfg=cfg(foo,values("bar",any())) // [mixed_values_any]compile-flags: --check-cfg=cfg(foo,values("bar",any()))
// [mixed_any]compile-flags: --check-cfg=cfg(any(),values(any())) // [mixed_any]compile-flags: --check-cfg=cfg(any(),values(any()))
// [any_values]compile-flags: --check-cfg=cfg(any(),values())
// [giberich]compile-flags: --check-cfg=cfg(...) // [giberich]compile-flags: --check-cfg=cfg(...)
// [unterminated]compile-flags: --check-cfg=cfg(
fn main() {} fn main() {}

View file

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(` (expected `cfg(name, values("value1", "value2", ... "valueN"))`)