Use explicit instead of implicit control-flow for check-cfg parsing

This commit is contained in:
Urgau 2023-04-30 11:51:36 +02:00
parent cad92b4c97
commit ad6f4b73eb

View File

@ -13,7 +13,8 @@ use rustc_middle::ty;
use rustc_parse::maybe_new_parser_from_source_str; use rustc_parse::maybe_new_parser_from_source_str;
use rustc_query_impl::QueryCtxt; use rustc_query_impl::QueryCtxt;
use rustc_query_system::query::print_query_stack; use rustc_query_system::query::print_query_stack;
use rustc_session::config::{self, CheckCfg, ErrorOutputType, Input, OutputFilenames}; use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames};
use rustc_session::config::{CheckCfg, ExpectedValues};
use rustc_session::lint; use rustc_session::lint;
use rustc_session::parse::{CrateConfig, ParseSess}; use rustc_session::parse::{CrateConfig, ParseSess};
use rustc_session::Session; use rustc_session::Session;
@ -121,9 +122,9 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String
/// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`. /// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`.
pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg { pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
rustc_span::create_default_session_if_not_set_then(move |_| { rustc_span::create_default_session_if_not_set_then(move |_| {
let mut cfg = CheckCfg::default(); let mut check_cfg = CheckCfg::default();
'specs: for s in specs { for s in specs {
let sess = ParseSess::with_silent_emitter(Some(format!( let sess = ParseSess::with_silent_emitter(Some(format!(
"this error occurred on the command line: `--check-cfg={s}`" "this error occurred on the command line: `--check-cfg={s}`"
))); )));
@ -137,17 +138,24 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"),
s s
), ),
); )
}; };
} }
let expected_error = || {
error!(
"expected `names(name1, name2, ... nameN)` or \
`values(name, \"value1\", \"value2\", ... \"valueN\")`"
)
};
match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) {
Ok(mut parser) => match parser.parse_meta_item() { Ok(mut parser) => match parser.parse_meta_item() {
Ok(meta_item) if parser.token == token::Eof => { Ok(meta_item) if parser.token == token::Eof => {
if let Some(args) = meta_item.meta_item_list() { if let Some(args) = meta_item.meta_item_list() {
if meta_item.has_name(sym::names) { if meta_item.has_name(sym::names) {
let names_valid = let names_valid =
cfg.names_valid.get_or_insert_with(|| FxHashSet::default()); check_cfg.names_valid.get_or_insert_with(|| FxHashSet::default());
for arg in args { for arg in args {
if arg.is_word() && arg.ident().is_some() { if arg.is_word() && arg.ident().is_some() {
let ident = arg.ident().expect("multi-segment cfg key"); let ident = arg.ident().expect("multi-segment cfg key");
@ -156,15 +164,20 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
error!("`names()` arguments must be simple identifiers"); error!("`names()` arguments must be simple identifiers");
} }
} }
continue 'specs;
} else if meta_item.has_name(sym::values) { } else if meta_item.has_name(sym::values) {
if let Some((name, values)) = args.split_first() { if let Some((name, values)) = args.split_first() {
if name.is_word() && name.ident().is_some() { if name.is_word() && name.ident().is_some() {
let ident = name.ident().expect("multi-segment cfg key"); let ident = name.ident().expect("multi-segment cfg key");
let ident_values = cfg let ident_values = check_cfg
.values_valid .values_valid
.entry(ident.name.to_string()) .entry(ident.name.to_string())
.or_insert_with(|| FxHashSet::default()); .or_insert_with(|| {
ExpectedValues::Some(FxHashSet::default())
});
let ExpectedValues::Some(expected_values) = expected_values else {
bug!("shoudn't be possible")
};
for val in values { for val in values {
if let Some(LitKind::Str(s, _)) = if let Some(LitKind::Str(s, _)) =
@ -177,36 +190,40 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
); );
} }
} }
continue 'specs;
} 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() {
cfg.well_known_values = true; check_cfg.well_known_values = true;
continue 'specs; } else {
expected_error();
}
} else {
expected_error();
}
} else {
expected_error();
} }
} }
Ok(..) => expected_error(),
Err(err) => {
err.cancel();
expected_error();
} }
}
Ok(..) => {}
Err(err) => err.cancel(),
}, },
Err(errs) => drop(errs), Err(errs) => {
drop(errs);
expected_error();
}
}
} }
error!( if let Some(names_valid) = &mut check_cfg.names_valid {
"expected `names(name1, name2, ... nameN)` or \ names_valid.extend(check_cfg.values_valid.keys().cloned());
`values(name, \"value1\", \"value2\", ... \"valueN\")`"
);
} }
check_cfg
if let Some(names_valid) = &mut cfg.names_valid {
names_valid.extend(cfg.values_valid.keys().cloned());
}
cfg
}) })
} }