From 98c469ce933612e9688f6b5a2ed9f83c1bb028ac Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 26 Oct 2023 17:12:57 +1100 Subject: [PATCH 1/7] Remove an unneeded dependency. --- Cargo.lock | 1 - compiler/rustc_interface/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff21d5f8c08..bd121921b0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4054,7 +4054,6 @@ dependencies = [ "rustc_hir_analysis", "rustc_hir_typeck", "rustc_incremental", - "rustc_index", "rustc_lint", "rustc_macros", "rustc_metadata", diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index ae008674d01..b280665057c 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -26,7 +26,6 @@ rustc_middle = { path = "../rustc_middle" } rustc_ast_lowering = { path = "../rustc_ast_lowering" } rustc_ast_passes = { path = "../rustc_ast_passes" } rustc_incremental = { path = "../rustc_incremental" } -rustc_index = { path = "../rustc_index" } rustc_traits = { path = "../rustc_traits" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } From 3feec48d70efc479ca0c14d65d89f001330b4fc1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 27 Oct 2023 08:24:49 +1100 Subject: [PATCH 2/7] Fix a comment. --- compiler/rustc_interface/src/callbacks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 45b1aeb4a5c..6fa989bb96c 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -26,7 +26,7 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { }) } -/// This is a callback from `rustc_ast` as it cannot access the implicit state +/// This is a callback from `rustc_errors` as it cannot access the implicit state /// in `rustc_middle` otherwise. It is used when diagnostic messages are /// emitted and stores them in the current query, if there is one. fn track_diagnostic(diagnostic: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) { From 2142d014ab9010ed87b3d5c865190bd1210c9073 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 27 Oct 2023 15:40:21 +1100 Subject: [PATCH 3/7] Streamline `rustc_interface` tests. In `test_edition_parsing`, change the `build_session_options_and_crate_config` call to `build_session_options`, because the config isn't used. That leaves a single call site for `build_session_options_and_crate_config`, so just inline and remove it. --- compiler/rustc_interface/src/tests.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 3d191669b1a..444c184dc2d 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -39,18 +39,10 @@ use std::sync::Arc; type CfgSpecs = FxHashSet<(String, Option)>; -fn build_session_options_and_crate_config( - handler: &mut EarlyErrorHandler, - matches: getopts::Matches, -) -> (Options, CfgSpecs) { - let sessopts = build_session_options(handler, &matches); - let cfg = parse_cfgspecs(handler, matches.opt_strs("cfg")); - (sessopts, cfg) -} - fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Session, CfgSpecs) { let registry = registry::Registry::new(&[]); - let (sessopts, cfg) = build_session_options_and_crate_config(handler, matches); + let sessopts = build_session_options(handler, &matches); + let cfg = parse_cfgspecs(handler, matches.opt_strs("cfg")); let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let io = CompilerIO { input: Input::Str { name: FileName::Custom(String::new()), input: String::new() }, @@ -880,6 +872,6 @@ fn test_edition_parsing() { let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); let matches = optgroups().parse(&["--edition=2018".to_string()]).unwrap(); - let (sessopts, _) = build_session_options_and_crate_config(&mut handler, matches); + let sessopts = build_session_options(&mut handler, &matches); assert!(sessopts.edition == Edition::Edition2018) } From 32986d895f9105de00a87d7f3d8897477ab64803 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 27 Oct 2023 15:49:09 +1100 Subject: [PATCH 4/7] Change `CrateConfig` from `FxIndexSet` to `FxHashSet`. Because its order doesn't matter. This is well demonstrated by `to_crate_config`, which creates a `CrateConfig` from an `FxHashSet`. --- compiler/rustc_session/src/parse.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index abb0ab5630c..316b9cc7acb 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -9,7 +9,7 @@ use crate::lint::{ builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId, }; use rustc_ast::node_id::NodeId; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, Handler}; use rustc_errors::{ @@ -27,7 +27,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 = FxIndexSet<(Symbol, Option)>; +pub type CrateConfig = FxHashSet<(Symbol, Option)>; pub type CrateCheckConfig = CheckCfg; /// Collected spans during parsing for places where a certain feature was @@ -237,7 +237,7 @@ impl ParseSess { Self { span_diagnostic: handler, unstable_features: UnstableFeatures::from_environment(None), - config: FxIndexSet::default(), + config: FxHashSet::default(), check_config: CrateCheckConfig::default(), edition: ExpnId::root().expn_data().edition, raw_identifier_spans: Default::default(), From 75e415ba86cc16ee5c0fd3c9007c94ea98995ab3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 27 Oct 2023 15:54:14 +1100 Subject: [PATCH 5/7] Optimize `parse_cfgspecs`. In `parse_cfg`, we now construct a `FxHashSet` directly instead of constructing a `FxHashSet` and then immediately converting it to a `FxHashSet`(!) (The type names made this behaviour non-obvious. The next commit will make the type names clearer.) --- compiler/rustc_interface/src/interface.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 87badcbdf15..26d7d26c31c 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -16,7 +16,7 @@ use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; use rustc_session::config::{self, CheckCfg, ExpectedValues, Input, OutFileName, OutputFilenames}; -use rustc_session::parse::{CrateConfig, ParseSess}; +use rustc_session::parse::ParseSess; use rustc_session::CompilerIO; use rustc_session::Session; use rustc_session::{lint, EarlyErrorHandler}; @@ -67,7 +67,7 @@ pub fn parse_cfgspecs( cfgspecs: Vec, ) -> FxHashSet<(String, Option)> { rustc_span::create_default_session_if_not_set_then(move |_| { - let cfg = cfgspecs + cfgspecs .into_iter() .map(|s| { let sess = ParseSess::with_silent_emitter(Some(format!( @@ -97,7 +97,10 @@ pub fn parse_cfgspecs( } MetaItemKind::NameValue(..) | MetaItemKind::Word => { let ident = meta_item.ident().expect("multi-segment cfg key"); - return (ident.name, meta_item.value_str()); + return ( + ident.name.to_string(), + meta_item.value_str().map(|sym| sym.to_string()), + ); } } } @@ -118,8 +121,7 @@ pub fn parse_cfgspecs( error!(r#"expected `key` or `key="value"`"#); } }) - .collect::(); - cfg.into_iter().map(|(a, b)| (a.to_string(), b.map(|b| b.to_string()))).collect() + .collect::>() }) } From 5e5499715714a383d76a3e69807e22093b616c66 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 27 Oct 2023 15:58:02 +1100 Subject: [PATCH 6/7] Clean up config mess. `parse_cfgspecs` and `parse_check_cfg` run very early, before the main interner is running. They each use a short-lived interner and convert all interned symbols to strings in their output data structures. Once the main interner starts up, these data structures get converted into new data structures that are identical except with the strings converted to symbols. All is not obvious from the current code, which is a mess, particularly with inconsistent naming that obscures the parallel string/symbol data structures. This commit clean things up a lot. - The existing `CheckCfg` type is generic, allowing both `CheckCfg` and `CheckCfg` forms. This is really useful, but it defaults to `String`. The commit removes the default so we have to use `CheckCfg` and `CheckCfg` explicitly, which makes things clearer. - Introduces `Cfg`, which is generic over `String` and `Symbol`, similar to `CheckCfg`. - Renames some things. - `parse_cfgspecs` -> `parse_cfg` - `CfgSpecs` -> `Cfg`, plus it's used in more places, rather than the underlying `FxHashSet` type. - `CrateConfig` -> `Cfg`. - `CrateCheckConfig` -> `CheckCfg` - Adds some comments explaining the string-to-symbol conversions. - `to_crate_check_config`, which converts `CheckCfg` to `CheckCfg`, is inlined and removed and combined with the overly-general `CheckCfg::map_data` to produce `CheckCfg::::intern`. - `build_configuration` now does the `Cfg`-to-`Cfg` conversion, so callers don't need to, which removes the need for `to_crate_config`. The diff for two of the fields in `Config` is a good example of the improved clarity: ``` - pub crate_cfg: FxHashSet<(String, Option)>, - pub crate_check_cfg: CheckCfg, + pub crate_cfg: Cfg, + pub crate_check_cfg: CheckCfg, ``` Compare that with the diff for the corresponding fields in `ParseSess`, and the relationship to `Config` is much clearer than before: ``` - pub config: CrateConfig, - pub check_config: CrateCheckConfig, + pub config: Cfg, + pub check_config: CheckCfg, ``` --- compiler/rustc_driver_impl/src/lib.rs | 2 +- compiler/rustc_interface/src/interface.rs | 27 +++++++------ compiler/rustc_interface/src/tests.rs | 21 +++++----- compiler/rustc_interface/src/util.rs | 20 +++++----- compiler/rustc_session/src/config.rs | 47 +++++++++++------------ compiler/rustc_session/src/parse.rs | 15 +++----- src/librustdoc/core.rs | 2 +- src/librustdoc/doctest.rs | 2 +- 8 files changed, 65 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 331843ab051..635930742fc 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -318,7 +318,7 @@ fn run_compiler( return Ok(()); } - let cfg = interface::parse_cfgspecs(&early_error_handler, matches.opt_strs("cfg")); + let cfg = interface::parse_cfg(&early_error_handler, matches.opt_strs("cfg")); let check_cfg = interface::parse_check_cfg(&early_error_handler, matches.opt_strs("check-cfg")); let (odir, ofile) = make_output(&matches); let mut config = interface::Config { diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 26d7d26c31c..7672523292b 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -15,7 +15,9 @@ use rustc_middle::{bug, ty}; use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; -use rustc_session::config::{self, CheckCfg, ExpectedValues, Input, OutFileName, OutputFilenames}; +use rustc_session::config::{ + self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName, OutputFilenames, +}; use rustc_session::parse::ParseSess; use rustc_session::CompilerIO; use rustc_session::Session; @@ -61,14 +63,13 @@ impl Compiler { } } -/// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`. -pub fn parse_cfgspecs( - handler: &EarlyErrorHandler, - cfgspecs: Vec, -) -> FxHashSet<(String, Option)> { +/// Converts strings provided as `--cfg [cfgspec]` into a `Cfg`. +pub fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec) -> Cfg { + // This creates a short-lived `SessionGlobals`, containing an interner. The + // parsed values are converted from symbols to strings before exiting + // because the symbols are meaningless once the interner is gone. rustc_span::create_default_session_if_not_set_then(move |_| { - cfgspecs - .into_iter() + cfgs.into_iter() .map(|s| { let sess = ParseSess::with_silent_emitter(Some(format!( "this error occurred on the command line: `--cfg={s}`" @@ -121,12 +122,14 @@ pub fn parse_cfgspecs( error!(r#"expected `key` or `key="value"`"#); } }) - .collect::>() + .collect::>() }) } /// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`. -pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> CheckCfg { +pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> CheckCfg { + // The comment about `SessionGlobals` and symbols in `parse_cfg` above + // applies here too. rustc_span::create_default_session_if_not_set_then(move |_| { // If any --check-cfg is passed then exhaustive_values and exhaustive_names // are enabled by default. @@ -374,8 +377,8 @@ pub struct Config { pub opts: config::Options, /// cfg! configuration in addition to the default ones - pub crate_cfg: FxHashSet<(String, Option)>, - pub crate_check_cfg: CheckCfg, + pub crate_cfg: Cfg, + pub crate_check_cfg: CheckCfg, pub input: Input, pub output_dir: Option, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 444c184dc2d..26cd83ac968 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -1,17 +1,16 @@ #![allow(rustc::bad_opt_access)] -use crate::interface::parse_cfgspecs; - -use rustc_data_structures::fx::FxHashSet; +use crate::interface::parse_cfg; use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::rustc_optgroups; +use rustc_session::config::Cfg; use rustc_session::config::DebugInfo; use rustc_session::config::Input; use rustc_session::config::InstrumentXRay; use rustc_session::config::LinkSelfContained; use rustc_session::config::Polonius; use rustc_session::config::TraitSolver; -use rustc_session::config::{build_configuration, build_session_options, to_crate_config}; +use rustc_session::config::{build_configuration, build_session_options}; use rustc_session::config::{ BranchProtection, Externs, OomStrategy, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, ProcMacroExecutionStrategy, SymbolManglingVersion, WasiExecModel, @@ -31,18 +30,18 @@ use rustc_span::FileName; use rustc_span::SourceFileHashAlgorithm; use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel}; use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel}; - use std::collections::{BTreeMap, BTreeSet}; use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; use std::sync::Arc; -type CfgSpecs = FxHashSet<(String, Option)>; - -fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Session, CfgSpecs) { +fn mk_session( + handler: &mut EarlyErrorHandler, + matches: getopts::Matches, +) -> (Session, Cfg) { let registry = registry::Registry::new(&[]); let sessopts = build_session_options(handler, &matches); - let cfg = parse_cfgspecs(handler, matches.opt_strs("cfg")); + let cfg = parse_cfg(handler, matches.opt_strs("cfg")); let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let io = CompilerIO { input: Input::Str { name: FileName::Custom(String::new()), input: String::new() }, @@ -133,7 +132,7 @@ fn test_switch_implies_cfg_test() { let matches = optgroups().parse(&["--test".to_string()]).unwrap(); let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); let (sess, cfg) = mk_session(&mut handler, matches); - let cfg = build_configuration(&sess, to_crate_config(cfg)); + let cfg = build_configuration(&sess, cfg); assert!(cfg.contains(&(sym::test, None))); }); } @@ -145,7 +144,7 @@ fn test_switch_implies_cfg_test_unless_cfg_test() { let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap(); let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); let (sess, cfg) = mk_session(&mut handler, matches); - let cfg = build_configuration(&sess, to_crate_config(cfg)); + let cfg = build_configuration(&sess, cfg); let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test); assert!(test_items.next().is_some()); assert!(test_items.next().is_none()); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index d2455a036cc..4d0be65697a 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -3,18 +3,17 @@ use info; use libloading::Library; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; #[cfg(parallel_compiler)] use rustc_data_structures::sync; use rustc_errors::registry::Registry; use rustc_parse::validate_attr; use rustc_session as session; -use rustc_session::config::CheckCfg; -use rustc_session::config::{self, CrateType}; -use rustc_session::config::{OutFileName, OutputFilenames, OutputTypes}; +use rustc_session::config::{ + self, Cfg, CheckCfg, CrateType, OutFileName, OutputFilenames, OutputTypes, +}; use rustc_session::filesearch::sysroot_candidates; use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer}; -use rustc_session::parse::CrateConfig; use rustc_session::{filesearch, output, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; @@ -38,7 +37,7 @@ pub type MakeBackendFn = fn() -> Box; /// This is performed by checking whether a set of permitted features /// is available on the target machine, by querying the codegen backend. pub fn add_configuration( - cfg: &mut CrateConfig, + cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dyn CodegenBackend, ) { @@ -60,8 +59,8 @@ pub fn add_configuration( pub fn create_session( handler: &EarlyErrorHandler, sopts: config::Options, - cfg: FxHashSet<(String, Option)>, - check_cfg: CheckCfg, + cfg: Cfg, + check_cfg: CheckCfg, locale_resources: &'static [&'static str], file_loader: Option>, io: CompilerIO, @@ -121,12 +120,13 @@ pub fn create_session( codegen_backend.init(&sess); - let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg)); + let mut cfg = config::build_configuration(&sess, cfg); add_configuration(&mut cfg, &mut sess, &*codegen_backend); - let mut check_cfg = config::to_crate_check_config(check_cfg); + let mut check_cfg = check_cfg.intern(); check_cfg.fill_well_known(&sess.target); + // These configs use symbols, rather than strings. sess.parse_sess.config = cfg; sess.parse_sess.check_config = check_cfg; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 7aced414ed6..fef4dfba6d2 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -16,7 +16,6 @@ use rustc_target::spec::LinkSelfContainedComponents; use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, SplitDebuginfo}; use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS}; -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}; @@ -1248,8 +1247,8 @@ pub const fn default_lib_output() -> CrateType { CrateType::Rlib } -fn default_configuration(sess: &Session) -> CrateConfig { - // NOTE: This should be kept in sync with `CrateCheckConfig::fill_well_known` below. +fn default_configuration(sess: &Session) -> Cfg { + // NOTE: This should be kept in sync with `CheckCfg::::fill_well_known` below. let end = &sess.target.endian; let arch = &sess.target.arch; let wordsz = sess.target.pointer_width.to_string(); @@ -1265,7 +1264,7 @@ fn default_configuration(sess: &Session) -> CrateConfig { sess.emit_fatal(err); }); - let mut ret = CrateConfig::default(); + let mut ret = Cfg::default(); ret.reserve(7); // the minimum number of insertions // Target bindings. ret.insert((sym::target_os, Some(Symbol::intern(os)))); @@ -1358,15 +1357,14 @@ fn default_configuration(sess: &Session) -> CrateConfig { ret } -/// Converts the crate `cfg!` configuration 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_config(cfg: FxHashSet<(String, Option)>) -> CrateConfig { - cfg.into_iter().map(|(a, b)| (Symbol::intern(&a), b.map(|b| Symbol::intern(&b)))).collect() -} +/// The parsed `--cfg` options that define the compilation environment of the +/// crate, used to drive conditional compilation. `T` is always `String` or +/// `Symbol`. Strings are used temporarily very early on. Once the the main +/// symbol interner is running, they are converted to symbols. +pub type Cfg = FxHashSet<(T, Option)>; -/// The parsed `--check-cfg` options -pub struct CheckCfg { +/// The parsed `--check-cfg` options. The `` structure is similar to `Cfg`. +pub struct CheckCfg { /// Is well known names activated pub exhaustive_names: bool, /// Is well known values activated @@ -1385,8 +1383,8 @@ impl Default for CheckCfg { } } -impl CheckCfg { - fn map_data(self, f: impl Fn(T) -> O) -> CheckCfg { +impl CheckCfg { + pub fn intern(self) -> CheckCfg { CheckCfg { exhaustive_names: self.exhaustive_names, exhaustive_values: self.exhaustive_values, @@ -1395,10 +1393,10 @@ impl CheckCfg { .into_iter() .map(|(name, values)| { ( - f(name), + Symbol::intern(&name), match values { ExpectedValues::Some(values) => ExpectedValues::Some( - values.into_iter().map(|b| b.map(|b| f(b))).collect(), + values.into_iter().map(|b| b.map(|b| Symbol::intern(&b))).collect(), ), ExpectedValues::Any => ExpectedValues::Any, }, @@ -1441,14 +1439,7 @@ impl<'a, T: Eq + Hash + Copy + 'a> Extend<&'a T> for ExpectedValues { } } -/// 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 { +impl CheckCfg { pub fn fill_well_known(&mut self, current_target: &Target) { if !self.exhaustive_values && !self.exhaustive_names { return; @@ -1588,7 +1579,13 @@ impl CrateCheckConfig { } } -pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig { +pub fn build_configuration(sess: &Session, user_cfg: Cfg) -> Cfg { + // We can now intern these strings. + let mut user_cfg: Cfg = user_cfg + .into_iter() + .map(|(a, b)| (Symbol::intern(&a), b.map(|b| Symbol::intern(&b)))) + .collect(); + // Combine the configuration requested by the session (command line) with // some default and generated configuration items. let default_cfg = default_configuration(sess); diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 316b9cc7acb..5b98ee5d992 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -1,7 +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::config::{Cfg, CheckCfg}; use crate::errors::{ CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError, }; @@ -25,11 +25,6 @@ use rustc_span::{Span, Symbol}; use rustc_ast::attr::AttrIdGenerator; 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`. #[derive(Default)] @@ -193,8 +188,8 @@ pub fn add_feature_diagnostics_for_issue( pub struct ParseSess { pub span_diagnostic: Handler, pub unstable_features: UnstableFeatures, - pub config: CrateConfig, - pub check_config: CrateCheckConfig, + pub config: Cfg, + pub check_config: CheckCfg, pub edition: Edition, /// Places where raw identifiers were used. This is used to avoid complaining about idents /// clashing with keywords in new editions. @@ -237,8 +232,8 @@ impl ParseSess { Self { span_diagnostic: handler, unstable_features: UnstableFeatures::from_environment(None), - config: FxHashSet::default(), - check_config: CrateCheckConfig::default(), + config: Cfg::default(), + check_config: CheckCfg::default(), edition: ExpnId::root().expn_data().edition, raw_identifier_spans: Default::default(), bad_unicode_identifiers: Lock::new(Default::default()), diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 94e557dcfdb..bcc61df7c4d 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -255,7 +255,7 @@ pub(crate) fn create_config( interface::Config { opts: sessopts, - crate_cfg: interface::parse_cfgspecs(handler, cfgs), + crate_cfg: interface::parse_cfg(handler, cfgs), crate_check_cfg: interface::parse_check_cfg(handler, check_cfgs), input, output_file: None, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 97913345e8f..c61c98e4de9 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -92,7 +92,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { cfgs.push("doctest".to_owned()); let config = interface::Config { opts: sessopts, - crate_cfg: interface::parse_cfgspecs(&early_error_handler, cfgs), + crate_cfg: interface::parse_cfg(&early_error_handler, cfgs), crate_check_cfg: interface::parse_check_cfg( &early_error_handler, options.check_cfgs.clone(), From 5438004766fc0f9b123608425b8ec7111f536640 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 28 Oct 2023 09:22:30 +1100 Subject: [PATCH 7/7] Change `Cfg` to an `FxIndexSet`. Despite what I claimed in an earlier commit, the ordering does matter to some degree. Using `FxIndexSet` prevents changes to the error message order in `tests/ui/check-cfg/mix.rs`. --- compiler/rustc_session/src/config.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index fef4dfba6d2..854e2b77993 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -9,7 +9,7 @@ use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; use crate::{lint, HashStableContext}; use crate::{EarlyErrorHandler, Session}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; use rustc_target::abi::Align; use rustc_target::spec::LinkSelfContainedComponents; @@ -1361,7 +1361,10 @@ fn default_configuration(sess: &Session) -> Cfg { /// crate, used to drive conditional compilation. `T` is always `String` or /// `Symbol`. Strings are used temporarily very early on. Once the the main /// symbol interner is running, they are converted to symbols. -pub type Cfg = FxHashSet<(T, Option)>; +/// +/// An `FxIndexSet` is used to ensure deterministic ordering of error messages +/// relating to `--cfg`. +pub type Cfg = FxIndexSet<(T, Option)>; /// The parsed `--check-cfg` options. The `` structure is similar to `Cfg`. pub struct CheckCfg {