Skip to content

Commit 5e54997

Browse files
committed
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<String>` and `CheckCfg<Symbol>` forms. This is really useful, but it defaults to `String`. The commit removes the default so we have to use `CheckCfg<String>` and `CheckCfg<Symbol>` 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<String>`, plus it's used in more places, rather than the underlying `FxHashSet` type. - `CrateConfig` -> `Cfg<Symbol>`. - `CrateCheckConfig` -> `CheckCfg<Symbol>` - Adds some comments explaining the string-to-symbol conversions. - `to_crate_check_config`, which converts `CheckCfg<String>` to `CheckCfg<Symbol>`, is inlined and removed and combined with the overly-general `CheckCfg::map_data` to produce `CheckCfg::<String>::intern`. - `build_configuration` now does the `Cfg<String>`-to-`Cfg<Symbol>` 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<String>)>, - pub crate_check_cfg: CheckCfg, + pub crate_cfg: Cfg<String>, + pub crate_check_cfg: CheckCfg<String>, ``` 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<Symbol>, + pub check_config: CheckCfg<Symbol>, ```
1 parent 75e415b commit 5e54997

File tree

8 files changed

+65
-71
lines changed

8 files changed

+65
-71
lines changed

compiler/rustc_driver_impl/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ fn run_compiler(
318318
return Ok(());
319319
}
320320

321-
let cfg = interface::parse_cfgspecs(&early_error_handler, matches.opt_strs("cfg"));
321+
let cfg = interface::parse_cfg(&early_error_handler, matches.opt_strs("cfg"));
322322
let check_cfg = interface::parse_check_cfg(&early_error_handler, matches.opt_strs("check-cfg"));
323323
let (odir, ofile) = make_output(&matches);
324324
let mut config = interface::Config {

compiler/rustc_interface/src/interface.rs

+15-12
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ use rustc_middle::{bug, ty};
1515
use rustc_parse::maybe_new_parser_from_source_str;
1616
use rustc_query_impl::QueryCtxt;
1717
use rustc_query_system::query::print_query_stack;
18-
use rustc_session::config::{self, CheckCfg, ExpectedValues, Input, OutFileName, OutputFilenames};
18+
use rustc_session::config::{
19+
self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName, OutputFilenames,
20+
};
1921
use rustc_session::parse::ParseSess;
2022
use rustc_session::CompilerIO;
2123
use rustc_session::Session;
@@ -61,14 +63,13 @@ impl Compiler {
6163
}
6264
}
6365

64-
/// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
65-
pub fn parse_cfgspecs(
66-
handler: &EarlyErrorHandler,
67-
cfgspecs: Vec<String>,
68-
) -> FxHashSet<(String, Option<String>)> {
66+
/// Converts strings provided as `--cfg [cfgspec]` into a `Cfg`.
67+
pub fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec<String>) -> Cfg<String> {
68+
// This creates a short-lived `SessionGlobals`, containing an interner. The
69+
// parsed values are converted from symbols to strings before exiting
70+
// because the symbols are meaningless once the interner is gone.
6971
rustc_span::create_default_session_if_not_set_then(move |_| {
70-
cfgspecs
71-
.into_iter()
72+
cfgs.into_iter()
7273
.map(|s| {
7374
let sess = ParseSess::with_silent_emitter(Some(format!(
7475
"this error occurred on the command line: `--cfg={s}`"
@@ -121,12 +122,14 @@ pub fn parse_cfgspecs(
121122
error!(r#"expected `key` or `key="value"`"#);
122123
}
123124
})
124-
.collect::<FxHashSet<_>>()
125+
.collect::<Cfg<String>>()
125126
})
126127
}
127128

128129
/// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`.
129-
pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> CheckCfg {
130+
pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> CheckCfg<String> {
131+
// The comment about `SessionGlobals` and symbols in `parse_cfg` above
132+
// applies here too.
130133
rustc_span::create_default_session_if_not_set_then(move |_| {
131134
// If any --check-cfg is passed then exhaustive_values and exhaustive_names
132135
// are enabled by default.
@@ -374,8 +377,8 @@ pub struct Config {
374377
pub opts: config::Options,
375378

376379
/// cfg! configuration in addition to the default ones
377-
pub crate_cfg: FxHashSet<(String, Option<String>)>,
378-
pub crate_check_cfg: CheckCfg,
380+
pub crate_cfg: Cfg<String>,
381+
pub crate_check_cfg: CheckCfg<String>,
379382

380383
pub input: Input,
381384
pub output_dir: Option<PathBuf>,

compiler/rustc_interface/src/tests.rs

+10-11
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
#![allow(rustc::bad_opt_access)]
2-
use crate::interface::parse_cfgspecs;
3-
4-
use rustc_data_structures::fx::FxHashSet;
2+
use crate::interface::parse_cfg;
53
use rustc_data_structures::profiling::TimePassesFormat;
64
use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
75
use rustc_session::config::rustc_optgroups;
6+
use rustc_session::config::Cfg;
87
use rustc_session::config::DebugInfo;
98
use rustc_session::config::Input;
109
use rustc_session::config::InstrumentXRay;
1110
use rustc_session::config::LinkSelfContained;
1211
use rustc_session::config::Polonius;
1312
use rustc_session::config::TraitSolver;
14-
use rustc_session::config::{build_configuration, build_session_options, to_crate_config};
13+
use rustc_session::config::{build_configuration, build_session_options};
1514
use rustc_session::config::{
1615
BranchProtection, Externs, OomStrategy, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet,
1716
ProcMacroExecutionStrategy, SymbolManglingVersion, WasiExecModel,
@@ -31,18 +30,18 @@ use rustc_span::FileName;
3130
use rustc_span::SourceFileHashAlgorithm;
3231
use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel};
3332
use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel};
34-
3533
use std::collections::{BTreeMap, BTreeSet};
3634
use std::num::NonZeroUsize;
3735
use std::path::{Path, PathBuf};
3836
use std::sync::Arc;
3937

40-
type CfgSpecs = FxHashSet<(String, Option<String>)>;
41-
42-
fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Session, CfgSpecs) {
38+
fn mk_session(
39+
handler: &mut EarlyErrorHandler,
40+
matches: getopts::Matches,
41+
) -> (Session, Cfg<String>) {
4342
let registry = registry::Registry::new(&[]);
4443
let sessopts = build_session_options(handler, &matches);
45-
let cfg = parse_cfgspecs(handler, matches.opt_strs("cfg"));
44+
let cfg = parse_cfg(handler, matches.opt_strs("cfg"));
4645
let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
4746
let io = CompilerIO {
4847
input: Input::Str { name: FileName::Custom(String::new()), input: String::new() },
@@ -133,7 +132,7 @@ fn test_switch_implies_cfg_test() {
133132
let matches = optgroups().parse(&["--test".to_string()]).unwrap();
134133
let mut handler = EarlyErrorHandler::new(ErrorOutputType::default());
135134
let (sess, cfg) = mk_session(&mut handler, matches);
136-
let cfg = build_configuration(&sess, to_crate_config(cfg));
135+
let cfg = build_configuration(&sess, cfg);
137136
assert!(cfg.contains(&(sym::test, None)));
138137
});
139138
}
@@ -145,7 +144,7 @@ fn test_switch_implies_cfg_test_unless_cfg_test() {
145144
let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap();
146145
let mut handler = EarlyErrorHandler::new(ErrorOutputType::default());
147146
let (sess, cfg) = mk_session(&mut handler, matches);
148-
let cfg = build_configuration(&sess, to_crate_config(cfg));
147+
let cfg = build_configuration(&sess, cfg);
149148
let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test);
150149
assert!(test_items.next().is_some());
151150
assert!(test_items.next().is_none());

compiler/rustc_interface/src/util.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,17 @@ use info;
33
use libloading::Library;
44
use rustc_ast as ast;
55
use rustc_codegen_ssa::traits::CodegenBackend;
6-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6+
use rustc_data_structures::fx::FxHashMap;
77
#[cfg(parallel_compiler)]
88
use rustc_data_structures::sync;
99
use rustc_errors::registry::Registry;
1010
use rustc_parse::validate_attr;
1111
use rustc_session as session;
12-
use rustc_session::config::CheckCfg;
13-
use rustc_session::config::{self, CrateType};
14-
use rustc_session::config::{OutFileName, OutputFilenames, OutputTypes};
12+
use rustc_session::config::{
13+
self, Cfg, CheckCfg, CrateType, OutFileName, OutputFilenames, OutputTypes,
14+
};
1515
use rustc_session::filesearch::sysroot_candidates;
1616
use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer};
17-
use rustc_session::parse::CrateConfig;
1817
use rustc_session::{filesearch, output, Session};
1918
use rustc_span::edit_distance::find_best_match_for_name;
2019
use rustc_span::edition::Edition;
@@ -38,7 +37,7 @@ pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
3837
/// This is performed by checking whether a set of permitted features
3938
/// is available on the target machine, by querying the codegen backend.
4039
pub fn add_configuration(
41-
cfg: &mut CrateConfig,
40+
cfg: &mut Cfg<Symbol>,
4241
sess: &mut Session,
4342
codegen_backend: &dyn CodegenBackend,
4443
) {
@@ -60,8 +59,8 @@ pub fn add_configuration(
6059
pub fn create_session(
6160
handler: &EarlyErrorHandler,
6261
sopts: config::Options,
63-
cfg: FxHashSet<(String, Option<String>)>,
64-
check_cfg: CheckCfg,
62+
cfg: Cfg<String>,
63+
check_cfg: CheckCfg<String>,
6564
locale_resources: &'static [&'static str],
6665
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
6766
io: CompilerIO,
@@ -121,12 +120,13 @@ pub fn create_session(
121120

122121
codegen_backend.init(&sess);
123122

124-
let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg));
123+
let mut cfg = config::build_configuration(&sess, cfg);
125124
add_configuration(&mut cfg, &mut sess, &*codegen_backend);
126125

127-
let mut check_cfg = config::to_crate_check_config(check_cfg);
126+
let mut check_cfg = check_cfg.intern();
128127
check_cfg.fill_well_known(&sess.target);
129128

129+
// These configs use symbols, rather than strings.
130130
sess.parse_sess.config = cfg;
131131
sess.parse_sess.check_config = check_cfg;
132132

compiler/rustc_session/src/config.rs

+22-25
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use rustc_target::spec::LinkSelfContainedComponents;
1616
use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, SplitDebuginfo};
1717
use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
1818

19-
use crate::parse::{CrateCheckConfig, CrateConfig};
2019
use rustc_feature::UnstableFeatures;
2120
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
2221
use rustc_span::source_map::{FileName, FilePathMapping};
@@ -1248,8 +1247,8 @@ pub const fn default_lib_output() -> CrateType {
12481247
CrateType::Rlib
12491248
}
12501249

1251-
fn default_configuration(sess: &Session) -> CrateConfig {
1252-
// NOTE: This should be kept in sync with `CrateCheckConfig::fill_well_known` below.
1250+
fn default_configuration(sess: &Session) -> Cfg<Symbol> {
1251+
// NOTE: This should be kept in sync with `CheckCfg::<Symbol>::fill_well_known` below.
12531252
let end = &sess.target.endian;
12541253
let arch = &sess.target.arch;
12551254
let wordsz = sess.target.pointer_width.to_string();
@@ -1265,7 +1264,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
12651264
sess.emit_fatal(err);
12661265
});
12671266

1268-
let mut ret = CrateConfig::default();
1267+
let mut ret = Cfg::default();
12691268
ret.reserve(7); // the minimum number of insertions
12701269
// Target bindings.
12711270
ret.insert((sym::target_os, Some(Symbol::intern(os))));
@@ -1358,15 +1357,14 @@ fn default_configuration(sess: &Session) -> CrateConfig {
13581357
ret
13591358
}
13601359

1361-
/// Converts the crate `cfg!` configuration from `String` to `Symbol`.
1362-
/// `rustc_interface::interface::Config` accepts this in the compiler configuration,
1363-
/// but the symbol interner is not yet set up then, so we must convert it later.
1364-
pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig {
1365-
cfg.into_iter().map(|(a, b)| (Symbol::intern(&a), b.map(|b| Symbol::intern(&b)))).collect()
1366-
}
1360+
/// The parsed `--cfg` options that define the compilation environment of the
1361+
/// crate, used to drive conditional compilation. `T` is always `String` or
1362+
/// `Symbol`. Strings are used temporarily very early on. Once the the main
1363+
/// symbol interner is running, they are converted to symbols.
1364+
pub type Cfg<T> = FxHashSet<(T, Option<T>)>;
13671365

1368-
/// The parsed `--check-cfg` options
1369-
pub struct CheckCfg<T = String> {
1366+
/// The parsed `--check-cfg` options. The `<T>` structure is similar to `Cfg`.
1367+
pub struct CheckCfg<T> {
13701368
/// Is well known names activated
13711369
pub exhaustive_names: bool,
13721370
/// Is well known values activated
@@ -1385,8 +1383,8 @@ impl<T> Default for CheckCfg<T> {
13851383
}
13861384
}
13871385

1388-
impl<T> CheckCfg<T> {
1389-
fn map_data<O: Eq + Hash>(self, f: impl Fn(T) -> O) -> CheckCfg<O> {
1386+
impl CheckCfg<String> {
1387+
pub fn intern(self) -> CheckCfg<Symbol> {
13901388
CheckCfg {
13911389
exhaustive_names: self.exhaustive_names,
13921390
exhaustive_values: self.exhaustive_values,
@@ -1395,10 +1393,10 @@ impl<T> CheckCfg<T> {
13951393
.into_iter()
13961394
.map(|(name, values)| {
13971395
(
1398-
f(name),
1396+
Symbol::intern(&name),
13991397
match values {
14001398
ExpectedValues::Some(values) => ExpectedValues::Some(
1401-
values.into_iter().map(|b| b.map(|b| f(b))).collect(),
1399+
values.into_iter().map(|b| b.map(|b| Symbol::intern(&b))).collect(),
14021400
),
14031401
ExpectedValues::Any => ExpectedValues::Any,
14041402
},
@@ -1441,14 +1439,7 @@ impl<'a, T: Eq + Hash + Copy + 'a> Extend<&'a T> for ExpectedValues<T> {
14411439
}
14421440
}
14431441

1444-
/// Converts the crate `--check-cfg` options from `String` to `Symbol`.
1445-
/// `rustc_interface::interface::Config` accepts this in the compiler configuration,
1446-
/// but the symbol interner is not yet set up then, so we must convert it later.
1447-
pub fn to_crate_check_config(cfg: CheckCfg) -> CrateCheckConfig {
1448-
cfg.map_data(|s| Symbol::intern(&s))
1449-
}
1450-
1451-
impl CrateCheckConfig {
1442+
impl CheckCfg<Symbol> {
14521443
pub fn fill_well_known(&mut self, current_target: &Target) {
14531444
if !self.exhaustive_values && !self.exhaustive_names {
14541445
return;
@@ -1588,7 +1579,13 @@ impl CrateCheckConfig {
15881579
}
15891580
}
15901581

1591-
pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig {
1582+
pub fn build_configuration(sess: &Session, user_cfg: Cfg<String>) -> Cfg<Symbol> {
1583+
// We can now intern these strings.
1584+
let mut user_cfg: Cfg<Symbol> = user_cfg
1585+
.into_iter()
1586+
.map(|(a, b)| (Symbol::intern(&a), b.map(|b| Symbol::intern(&b))))
1587+
.collect();
1588+
15921589
// Combine the configuration requested by the session (command line) with
15931590
// some default and generated configuration items.
15941591
let default_cfg = default_configuration(sess);

compiler/rustc_session/src/parse.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Contains `ParseSess` which holds state living beyond what one `Parser` might.
22
//! It also serves as an input to the parser itself.
33
4-
use crate::config::CheckCfg;
4+
use crate::config::{Cfg, CheckCfg};
55
use crate::errors::{
66
CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError,
77
};
@@ -25,11 +25,6 @@ use rustc_span::{Span, Symbol};
2525
use rustc_ast::attr::AttrIdGenerator;
2626
use std::str;
2727

28-
/// The set of keys (and, optionally, values) that define the compilation
29-
/// environment of the crate, used to drive conditional compilation.
30-
pub type CrateConfig = FxHashSet<(Symbol, Option<Symbol>)>;
31-
pub type CrateCheckConfig = CheckCfg<Symbol>;
32-
3328
/// Collected spans during parsing for places where a certain feature was
3429
/// used and should be feature gated accordingly in `check_crate`.
3530
#[derive(Default)]
@@ -193,8 +188,8 @@ pub fn add_feature_diagnostics_for_issue(
193188
pub struct ParseSess {
194189
pub span_diagnostic: Handler,
195190
pub unstable_features: UnstableFeatures,
196-
pub config: CrateConfig,
197-
pub check_config: CrateCheckConfig,
191+
pub config: Cfg<Symbol>,
192+
pub check_config: CheckCfg<Symbol>,
198193
pub edition: Edition,
199194
/// Places where raw identifiers were used. This is used to avoid complaining about idents
200195
/// clashing with keywords in new editions.
@@ -237,8 +232,8 @@ impl ParseSess {
237232
Self {
238233
span_diagnostic: handler,
239234
unstable_features: UnstableFeatures::from_environment(None),
240-
config: FxHashSet::default(),
241-
check_config: CrateCheckConfig::default(),
235+
config: Cfg::default(),
236+
check_config: CheckCfg::default(),
242237
edition: ExpnId::root().expn_data().edition,
243238
raw_identifier_spans: Default::default(),
244239
bad_unicode_identifiers: Lock::new(Default::default()),

src/librustdoc/core.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ pub(crate) fn create_config(
255255

256256
interface::Config {
257257
opts: sessopts,
258-
crate_cfg: interface::parse_cfgspecs(handler, cfgs),
258+
crate_cfg: interface::parse_cfg(handler, cfgs),
259259
crate_check_cfg: interface::parse_check_cfg(handler, check_cfgs),
260260
input,
261261
output_file: None,

src/librustdoc/doctest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
9292
cfgs.push("doctest".to_owned());
9393
let config = interface::Config {
9494
opts: sessopts,
95-
crate_cfg: interface::parse_cfgspecs(&early_error_handler, cfgs),
95+
crate_cfg: interface::parse_cfg(&early_error_handler, cfgs),
9696
crate_check_cfg: interface::parse_check_cfg(
9797
&early_error_handler,
9898
options.check_cfgs.clone(),

0 commit comments

Comments
 (0)