mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-03 02:23:20 +00:00
Improve CheckCfg internal representation
This commit is contained in:
parent
cb4ee81ef5
commit
da896d35f4
@ -463,27 +463,30 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
|
||||
MetaItemKind::NameValue(..) | MetaItemKind::Word => {
|
||||
let name = cfg.ident().expect("multi-segment cfg predicate").name;
|
||||
let value = cfg.value_str();
|
||||
if sess.check_config.names_checked && !sess.check_config.names_valid.contains(&name)
|
||||
{
|
||||
sess.buffer_lint(
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
CRATE_NODE_ID,
|
||||
"unexpected `cfg` condition name",
|
||||
);
|
||||
}
|
||||
if let Some(val) = value {
|
||||
if sess.check_config.values_checked.contains(&name)
|
||||
&& !sess.check_config.values_valid.contains(&(name, val))
|
||||
{
|
||||
if let Some(names_valid) = &sess.check_config.names_valid {
|
||||
if !names_valid.contains(&name) {
|
||||
sess.buffer_lint(
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
CRATE_NODE_ID,
|
||||
"unexpected `cfg` condition value",
|
||||
"unexpected `cfg` condition name",
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(val) = value {
|
||||
if let Some(values_valid) = &sess.check_config.values_valid {
|
||||
if let Some(values) = values_valid.get(&name) {
|
||||
if !values.contains(&val) {
|
||||
sess.buffer_lint(
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
CRATE_NODE_ID,
|
||||
"unexpected `cfg` condition value",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sess.config.contains(&(name, value))
|
||||
}
|
||||
}
|
||||
|
@ -169,11 +169,12 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
|
||||
Ok(meta_item) if parser.token == token::Eof => {
|
||||
if let Some(args) = meta_item.meta_item_list() {
|
||||
if meta_item.has_name(sym::names) {
|
||||
cfg.names_checked = true;
|
||||
let names_valid =
|
||||
cfg.names_valid.get_or_insert_with(|| FxHashSet::default());
|
||||
for arg in args {
|
||||
if arg.is_word() && arg.ident().is_some() {
|
||||
let ident = arg.ident().expect("multi-segment cfg key");
|
||||
cfg.names_valid.insert(ident.name.to_string());
|
||||
names_valid.insert(ident.name.to_string());
|
||||
} else {
|
||||
error!("`names()` arguments must be simple identifers");
|
||||
}
|
||||
@ -182,14 +183,19 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
|
||||
} else if meta_item.has_name(sym::values) {
|
||||
if let Some((name, values)) = args.split_first() {
|
||||
if name.is_word() && name.ident().is_some() {
|
||||
let values_valid = cfg
|
||||
.values_valid
|
||||
.get_or_insert_with(|| FxHashMap::default());
|
||||
let ident = name.ident().expect("multi-segment cfg key");
|
||||
cfg.values_checked.insert(ident.to_string());
|
||||
let ident_values = values_valid
|
||||
.entry(ident.to_string())
|
||||
.or_insert_with(|| FxHashSet::default());
|
||||
|
||||
for val in values {
|
||||
if let Some(LitKind::Str(s, _)) =
|
||||
val.literal().map(|lit| &lit.kind)
|
||||
{
|
||||
cfg.values_valid
|
||||
.insert((ident.to_string(), s.to_string()));
|
||||
ident_values.insert(s.to_string());
|
||||
} else {
|
||||
error!(
|
||||
"`values()` arguments must be string literals"
|
||||
@ -219,7 +225,11 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
|
||||
);
|
||||
}
|
||||
|
||||
cfg.names_valid.extend(cfg.values_checked.iter().cloned());
|
||||
if let Some(values_valid) = &cfg.values_valid {
|
||||
if let Some(names_valid) = &mut cfg.names_valid {
|
||||
names_valid.extend(values_valid.keys().cloned());
|
||||
}
|
||||
}
|
||||
cfg
|
||||
})
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use crate::search_paths::SearchPath;
|
||||
use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
|
||||
use crate::{early_error, early_warn, Session};
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::impl_stable_hash_via_hash;
|
||||
|
||||
use rustc_target::abi::{Align, TargetDataLayout};
|
||||
@ -1023,34 +1023,28 @@ pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig
|
||||
|
||||
/// The parsed `--check-cfg` options
|
||||
pub struct CheckCfg<T = String> {
|
||||
/// Set if `names()` checking is enabled
|
||||
pub names_checked: bool,
|
||||
/// The union of all `names()`
|
||||
pub names_valid: FxHashSet<T>,
|
||||
/// The set of names for which `values()` was used
|
||||
pub values_checked: FxHashSet<T>,
|
||||
/// The set of all (name, value) pairs passed in `values()`
|
||||
pub values_valid: FxHashSet<(T, T)>,
|
||||
/// The set of all `names()`, if none no names checking is performed
|
||||
pub names_valid: Option<FxHashSet<T>>,
|
||||
/// The set of all `values()`, if none no values chcking is performed
|
||||
pub values_valid: Option<FxHashMap<T, FxHashSet<T>>>,
|
||||
}
|
||||
|
||||
impl<T> Default for CheckCfg<T> {
|
||||
fn default() -> Self {
|
||||
CheckCfg {
|
||||
names_checked: false,
|
||||
names_valid: FxHashSet::default(),
|
||||
values_checked: FxHashSet::default(),
|
||||
values_valid: FxHashSet::default(),
|
||||
}
|
||||
CheckCfg { names_valid: Default::default(), values_valid: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CheckCfg<T> {
|
||||
fn map_data<O: Eq + Hash>(&self, f: impl Fn(&T) -> O) -> CheckCfg<O> {
|
||||
CheckCfg {
|
||||
names_checked: self.names_checked,
|
||||
names_valid: self.names_valid.iter().map(|a| f(a)).collect(),
|
||||
values_checked: self.values_checked.iter().map(|a| f(a)).collect(),
|
||||
values_valid: self.values_valid.iter().map(|(a, b)| (f(a), f(b))).collect(),
|
||||
names_valid: self
|
||||
.names_valid
|
||||
.as_ref()
|
||||
.map(|names_valid| names_valid.iter().map(|a| f(a)).collect()),
|
||||
values_valid: self.values_valid.as_ref().map(|values_valid| {
|
||||
values_valid.iter().map(|(a, b)| (f(a), b.iter().map(|b| f(b)).collect())).collect()
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1090,17 +1084,25 @@ impl CrateCheckConfig {
|
||||
sym::doctest,
|
||||
sym::feature,
|
||||
];
|
||||
for &name in WELL_KNOWN_NAMES {
|
||||
self.names_valid.insert(name);
|
||||
if let Some(names_valid) = &mut self.names_valid {
|
||||
for &name in WELL_KNOWN_NAMES {
|
||||
names_valid.insert(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fills a `CrateCheckConfig` with configuration names and values that are actually active.
|
||||
pub fn fill_actual(&mut self, cfg: &CrateConfig) {
|
||||
for &(k, v) in cfg {
|
||||
self.names_valid.insert(k);
|
||||
if let Some(names_valid) = &mut self.names_valid {
|
||||
names_valid.insert(k);
|
||||
}
|
||||
if let Some(v) = v {
|
||||
self.values_valid.insert((k, v));
|
||||
if let Some(values_valid) = &mut self.values_valid {
|
||||
values_valid.entry(k).and_modify(|values| {
|
||||
values.insert(v);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user