From 3a73ca587bb8a8fb52d6045fbe31d50d5a56ff19 Mon Sep 17 00:00:00 2001 From: Loïc BRANSTETT Date: Wed, 29 Sep 2021 02:39:30 +0200 Subject: Implement --check-cfg option (RFC 3013) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Urgau Co-authored-by: Marcelina Kościelnicka --- compiler/rustc_session/src/config.rs | 89 +++++++++++++++++++++++++++++++++++- compiler/rustc_session/src/parse.rs | 4 ++ 2 files changed, 92 insertions(+), 1 deletion(-) (limited to 'compiler/rustc_session/src') diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 8630ffec241..f90766875d2 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -16,7 +16,7 @@ use rustc_target::spec::{LinkerFlavor, SplitDebuginfo, Target, TargetTriple, Tar use rustc_serialize::json; -use crate::parse::CrateConfig; +use crate::parse::{CrateCheckConfig, CrateConfig}; use rustc_feature::UnstableFeatures; use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION}; use rustc_span::source_map::{FileName, FilePathMapping}; @@ -921,6 +921,7 @@ pub const fn default_lib_output() -> CrateType { } fn default_configuration(sess: &Session) -> CrateConfig { + // NOTE: This should be kept in sync with `CrateCheckConfig::fill_well_known` below. let end = &sess.target.endian; let arch = &sess.target.arch; let wordsz = sess.target.pointer_width.to_string(); @@ -1005,6 +1006,91 @@ pub fn to_crate_config(cfg: FxHashSet<(String, Option)>) -> CrateConfig cfg.into_iter().map(|(a, b)| (Symbol::intern(&a), b.map(|b| Symbol::intern(&b)))).collect() } +/// The parsed `--check-cfg` options +pub struct CheckCfg { + /// Set if `names()` checking is enabled + pub names_checked: bool, + /// The union of all `names()` + pub names_valid: FxHashSet, + /// The set of names for which `values()` was used + pub values_checked: FxHashSet, + /// The set of all (name, value) pairs passed in `values()` + pub values_valid: FxHashSet<(T, T)>, +} + +impl Default for CheckCfg { + fn default() -> Self { + CheckCfg { + names_checked: false, + names_valid: FxHashSet::default(), + values_checked: FxHashSet::default(), + values_valid: FxHashSet::default(), + } + } +} + +impl CheckCfg { + fn map_data(&self, f: impl Fn(&T) -> O) -> CheckCfg { + 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(), + } + } +} + +/// Converts the crate `--check-cfg` options from `String` to `Symbol`. +/// `rustc_interface::interface::Config` accepts this in the compiler configuration, +/// but the symbol interner is not yet set up then, so we must convert it later. +pub fn to_crate_check_config(cfg: CheckCfg) -> CrateCheckConfig { + cfg.map_data(|s| Symbol::intern(s)) +} + +impl CrateCheckConfig { + /// Fills a `CrateCheckConfig` with well-known configuration names. + pub fn fill_well_known(&mut self) { + // NOTE: This should be kept in sync with `default_configuration` + const WELL_KNOWN_NAMES: &[Symbol] = &[ + sym::unix, + sym::windows, + sym::target_os, + sym::target_family, + sym::target_arch, + sym::target_endian, + sym::target_pointer_width, + sym::target_env, + sym::target_abi, + sym::target_vendor, + sym::target_thread_local, + sym::target_has_atomic_load_store, + sym::target_has_atomic, + sym::target_has_atomic_equal_alignment, + sym::panic, + sym::sanitize, + sym::debug_assertions, + sym::proc_macro, + sym::test, + sym::doc, + sym::doctest, + sym::feature, + ]; + for &name in WELL_KNOWN_NAMES { + self.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(v) = v { + self.values_valid.insert((k, v)); + } + } + } +} + pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig { // Combine the configuration requested by the session (command line) with // some default and generated configuration items. @@ -1148,6 +1234,7 @@ pub fn rustc_short_optgroups() -> Vec { vec![ opt::flag_s("h", "help", "Display this message"), opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"), + opt::multi("", "check-cfg", "Provide list of valid cfg options for checking", "SPEC"), opt::multi_s( "L", "", diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index d5b520325e5..7113f9b0a2f 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -1,6 +1,7 @@ //! Contains `ParseSess` which holds state living beyond what one `Parser` might. //! It also serves as an input to the parser itself. +use crate::config::CheckCfg; use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId}; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -18,6 +19,7 @@ use std::str; /// The set of keys (and, optionally, values) that define the compilation /// environment of the crate, used to drive conditional compilation. pub type CrateConfig = FxHashSet<(Symbol, Option)>; +pub type CrateCheckConfig = CheckCfg; /// Collected spans during parsing for places where a certain feature was /// used and should be feature gated accordingly in `check_crate`. @@ -117,6 +119,7 @@ pub struct ParseSess { pub span_diagnostic: Handler, pub unstable_features: UnstableFeatures, pub config: CrateConfig, + pub check_config: CrateCheckConfig, pub edition: Edition, pub missing_fragment_specifiers: Lock>, /// Places where raw identifiers were used. This is used to avoid complaining about idents @@ -162,6 +165,7 @@ impl ParseSess { span_diagnostic: handler, unstable_features: UnstableFeatures::from_environment(None), config: FxHashSet::default(), + check_config: CrateCheckConfig::default(), edition: ExpnId::root().expn_data().edition, missing_fragment_specifiers: Default::default(), raw_identifier_spans: Lock::new(Vec::new()), -- cgit 1.4.1-3-g733a5