Skip to content

Commit da896d3

Browse files
committed
Improve CheckCfg internal representation
1 parent cb4ee81 commit da896d3

File tree

3 files changed

+58
-43
lines changed

3 files changed

+58
-43
lines changed

compiler/rustc_attr/src/builtin.rs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -463,27 +463,30 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
463463
MetaItemKind::NameValue(..) | MetaItemKind::Word => {
464464
let name = cfg.ident().expect("multi-segment cfg predicate").name;
465465
let value = cfg.value_str();
466-
if sess.check_config.names_checked && !sess.check_config.names_valid.contains(&name)
467-
{
468-
sess.buffer_lint(
469-
UNEXPECTED_CFGS,
470-
cfg.span,
471-
CRATE_NODE_ID,
472-
"unexpected `cfg` condition name",
473-
);
474-
}
475-
if let Some(val) = value {
476-
if sess.check_config.values_checked.contains(&name)
477-
&& !sess.check_config.values_valid.contains(&(name, val))
478-
{
466+
if let Some(names_valid) = &sess.check_config.names_valid {
467+
if !names_valid.contains(&name) {
479468
sess.buffer_lint(
480469
UNEXPECTED_CFGS,
481470
cfg.span,
482471
CRATE_NODE_ID,
483-
"unexpected `cfg` condition value",
472+
"unexpected `cfg` condition name",
484473
);
485474
}
486475
}
476+
if let Some(val) = value {
477+
if let Some(values_valid) = &sess.check_config.values_valid {
478+
if let Some(values) = values_valid.get(&name) {
479+
if !values.contains(&val) {
480+
sess.buffer_lint(
481+
UNEXPECTED_CFGS,
482+
cfg.span,
483+
CRATE_NODE_ID,
484+
"unexpected `cfg` condition value",
485+
);
486+
}
487+
}
488+
}
489+
}
487490
sess.config.contains(&(name, value))
488491
}
489492
}

compiler/rustc_interface/src/interface.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,12 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
169169
Ok(meta_item) if parser.token == token::Eof => {
170170
if let Some(args) = meta_item.meta_item_list() {
171171
if meta_item.has_name(sym::names) {
172-
cfg.names_checked = true;
172+
let names_valid =
173+
cfg.names_valid.get_or_insert_with(|| FxHashSet::default());
173174
for arg in args {
174175
if arg.is_word() && arg.ident().is_some() {
175176
let ident = arg.ident().expect("multi-segment cfg key");
176-
cfg.names_valid.insert(ident.name.to_string());
177+
names_valid.insert(ident.name.to_string());
177178
} else {
178179
error!("`names()` arguments must be simple identifers");
179180
}
@@ -182,14 +183,19 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
182183
} else if meta_item.has_name(sym::values) {
183184
if let Some((name, values)) = args.split_first() {
184185
if name.is_word() && name.ident().is_some() {
186+
let values_valid = cfg
187+
.values_valid
188+
.get_or_insert_with(|| FxHashMap::default());
185189
let ident = name.ident().expect("multi-segment cfg key");
186-
cfg.values_checked.insert(ident.to_string());
190+
let ident_values = values_valid
191+
.entry(ident.to_string())
192+
.or_insert_with(|| FxHashSet::default());
193+
187194
for val in values {
188195
if let Some(LitKind::Str(s, _)) =
189196
val.literal().map(|lit| &lit.kind)
190197
{
191-
cfg.values_valid
192-
.insert((ident.to_string(), s.to_string()));
198+
ident_values.insert(s.to_string());
193199
} else {
194200
error!(
195201
"`values()` arguments must be string literals"
@@ -219,7 +225,11 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
219225
);
220226
}
221227

222-
cfg.names_valid.extend(cfg.values_checked.iter().cloned());
228+
if let Some(values_valid) = &cfg.values_valid {
229+
if let Some(names_valid) = &mut cfg.names_valid {
230+
names_valid.extend(values_valid.keys().cloned());
231+
}
232+
}
223233
cfg
224234
})
225235
}

compiler/rustc_session/src/config.rs

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::search_paths::SearchPath;
88
use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
99
use crate::{early_error, early_warn, Session};
1010

11-
use rustc_data_structures::fx::FxHashSet;
11+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1212
use rustc_data_structures::impl_stable_hash_via_hash;
1313

1414
use rustc_target::abi::{Align, TargetDataLayout};
@@ -1023,34 +1023,28 @@ pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig
10231023

10241024
/// The parsed `--check-cfg` options
10251025
pub struct CheckCfg<T = String> {
1026-
/// Set if `names()` checking is enabled
1027-
pub names_checked: bool,
1028-
/// The union of all `names()`
1029-
pub names_valid: FxHashSet<T>,
1030-
/// The set of names for which `values()` was used
1031-
pub values_checked: FxHashSet<T>,
1032-
/// The set of all (name, value) pairs passed in `values()`
1033-
pub values_valid: FxHashSet<(T, T)>,
1026+
/// The set of all `names()`, if none no names checking is performed
1027+
pub names_valid: Option<FxHashSet<T>>,
1028+
/// The set of all `values()`, if none no values chcking is performed
1029+
pub values_valid: Option<FxHashMap<T, FxHashSet<T>>>,
10341030
}
10351031

10361032
impl<T> Default for CheckCfg<T> {
10371033
fn default() -> Self {
1038-
CheckCfg {
1039-
names_checked: false,
1040-
names_valid: FxHashSet::default(),
1041-
values_checked: FxHashSet::default(),
1042-
values_valid: FxHashSet::default(),
1043-
}
1034+
CheckCfg { names_valid: Default::default(), values_valid: Default::default() }
10441035
}
10451036
}
10461037

10471038
impl<T> CheckCfg<T> {
10481039
fn map_data<O: Eq + Hash>(&self, f: impl Fn(&T) -> O) -> CheckCfg<O> {
10491040
CheckCfg {
1050-
names_checked: self.names_checked,
1051-
names_valid: self.names_valid.iter().map(|a| f(a)).collect(),
1052-
values_checked: self.values_checked.iter().map(|a| f(a)).collect(),
1053-
values_valid: self.values_valid.iter().map(|(a, b)| (f(a), f(b))).collect(),
1041+
names_valid: self
1042+
.names_valid
1043+
.as_ref()
1044+
.map(|names_valid| names_valid.iter().map(|a| f(a)).collect()),
1045+
values_valid: self.values_valid.as_ref().map(|values_valid| {
1046+
values_valid.iter().map(|(a, b)| (f(a), b.iter().map(|b| f(b)).collect())).collect()
1047+
}),
10541048
}
10551049
}
10561050
}
@@ -1090,17 +1084,25 @@ impl CrateCheckConfig {
10901084
sym::doctest,
10911085
sym::feature,
10921086
];
1093-
for &name in WELL_KNOWN_NAMES {
1094-
self.names_valid.insert(name);
1087+
if let Some(names_valid) = &mut self.names_valid {
1088+
for &name in WELL_KNOWN_NAMES {
1089+
names_valid.insert(name);
1090+
}
10951091
}
10961092
}
10971093

10981094
/// Fills a `CrateCheckConfig` with configuration names and values that are actually active.
10991095
pub fn fill_actual(&mut self, cfg: &CrateConfig) {
11001096
for &(k, v) in cfg {
1101-
self.names_valid.insert(k);
1097+
if let Some(names_valid) = &mut self.names_valid {
1098+
names_valid.insert(k);
1099+
}
11021100
if let Some(v) = v {
1103-
self.values_valid.insert((k, v));
1101+
if let Some(values_valid) = &mut self.values_valid {
1102+
values_valid.entry(k).and_modify(|values| {
1103+
values.insert(v);
1104+
});
1105+
}
11041106
}
11051107
}
11061108
}

0 commit comments

Comments
 (0)