about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorLoïc BRANSTETT <lolo.branstett@numericable.fr>2022-02-19 23:06:11 +0100
committerLoïc BRANSTETT <lolo.branstett@numericable.fr>2022-02-22 22:41:49 +0100
commitda896d35f471a27eb7b9385d6eadf50a5f761265 (patch)
tree4ccc8f3571c097b8c232031bbcebe61b81454d0c /compiler
parentcb4ee81ef555126e49b3e9f16ca6f12a3264a451 (diff)
downloadrust-da896d35f471a27eb7b9385d6eadf50a5f761265.tar.gz
rust-da896d35f471a27eb7b9385d6eadf50a5f761265.zip
Improve CheckCfg internal representation
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_attr/src/builtin.rs31
-rw-r--r--compiler/rustc_interface/src/interface.rs22
-rw-r--r--compiler/rustc_session/src/config.rs48
3 files changed, 58 insertions, 43 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 49043e9f5f9..cd2e150a190 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -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))
             }
         }
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 609fc4b78c0..5e0d59bf1b1 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -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
     })
 }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 7a0d9a212c9..e0a3cc78b17 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -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);
+                    });
+                }
             }
         }
     }