Skip to content

Commit 5b8b236

Browse files
authored
Rollup merge of rust-lang#123519 - Urgau:session-cfg-check-cfg-improvements, r=wesleywiser
Improve cfg and check-cfg configuration This PR improves cfg and check-cfg configuration by: 1. Extracting both logic under a common module (to improve the connection between the two) 2. Adding more documentation, in particular some steps when adding a new cfg I also added my-self as mention in our triagebot conf for the new module. Inspired by rust-lang#123411 (comment)
2 parents 7988adf + c39c0e1 commit 5b8b236

File tree

3 files changed

+384
-342
lines changed

3 files changed

+384
-342
lines changed

compiler/rustc_session/src/config.rs

+6-342
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,16 @@ use crate::search_paths::SearchPath;
1010
use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
1111
use crate::{filesearch, lint, HashStableContext};
1212
use crate::{EarlyDiagCtxt, Session};
13-
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
13+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
1414
use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
1515
use rustc_errors::emitter::HumanReadableErrorType;
1616
use rustc_errors::{ColorConfig, DiagArgValue, DiagCtxtFlags, IntoDiagArg};
1717
use rustc_feature::UnstableFeatures;
1818
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
1919
use rustc_span::source_map::FilePathMapping;
20-
use rustc_span::symbol::{sym, Symbol};
2120
use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm};
22-
use rustc_target::abi::Align;
2321
use rustc_target::spec::LinkSelfContainedComponents;
24-
use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, SplitDebuginfo};
25-
use rustc_target::spec::{Target, TargetTriple, TARGETS};
22+
use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple};
2623
use std::collections::btree_map::{
2724
Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
2825
};
@@ -36,8 +33,11 @@ use std::path::{Path, PathBuf};
3633
use std::str::{self, FromStr};
3734
use std::sync::LazyLock;
3835

36+
mod cfg;
3937
pub mod sigpipe;
4038

39+
pub use cfg::{Cfg, CheckCfg, ExpectedValues};
40+
4141
/// The different settings that the `-C strip` flag can have.
4242
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
4343
pub enum Strip {
@@ -1201,346 +1201,10 @@ pub(crate) const fn default_lib_output() -> CrateType {
12011201
CrateType::Rlib
12021202
}
12031203

1204-
fn default_configuration(sess: &Session) -> Cfg {
1205-
let mut ret = Cfg::default();
1206-
1207-
macro_rules! ins_none {
1208-
($key:expr) => {
1209-
ret.insert(($key, None));
1210-
};
1211-
}
1212-
macro_rules! ins_str {
1213-
($key:expr, $val_str:expr) => {
1214-
ret.insert(($key, Some(Symbol::intern($val_str))));
1215-
};
1216-
}
1217-
macro_rules! ins_sym {
1218-
($key:expr, $val_sym:expr) => {
1219-
ret.insert(($key, Some($val_sym)));
1220-
};
1221-
}
1222-
1223-
// Symbols are inserted in alphabetical order as much as possible.
1224-
// The exceptions are where control flow forces things out of order.
1225-
//
1226-
// Run `rustc --print cfg` to see the configuration in practice.
1227-
//
1228-
// NOTE: These insertions should be kept in sync with
1229-
// `CheckCfg::fill_well_known` below.
1230-
1231-
if sess.opts.debug_assertions {
1232-
ins_none!(sym::debug_assertions);
1233-
}
1234-
1235-
if sess.overflow_checks() {
1236-
ins_none!(sym::overflow_checks);
1237-
}
1238-
1239-
ins_sym!(sym::panic, sess.panic_strategy().desc_symbol());
1240-
1241-
// JUSTIFICATION: before wrapper fn is available
1242-
#[allow(rustc::bad_opt_access)]
1243-
if sess.opts.crate_types.contains(&CrateType::ProcMacro) {
1244-
ins_none!(sym::proc_macro);
1245-
}
1246-
1247-
if sess.is_nightly_build() {
1248-
ins_sym!(sym::relocation_model, sess.target.relocation_model.desc_symbol());
1249-
}
1250-
1251-
for mut s in sess.opts.unstable_opts.sanitizer {
1252-
// KASAN is still ASAN under the hood, so it uses the same attribute.
1253-
if s == SanitizerSet::KERNELADDRESS {
1254-
s = SanitizerSet::ADDRESS;
1255-
}
1256-
ins_str!(sym::sanitize, &s.to_string());
1257-
}
1258-
1259-
if sess.is_sanitizer_cfi_generalize_pointers_enabled() {
1260-
ins_none!(sym::sanitizer_cfi_generalize_pointers);
1261-
}
1262-
if sess.is_sanitizer_cfi_normalize_integers_enabled() {
1263-
ins_none!(sym::sanitizer_cfi_normalize_integers);
1264-
}
1265-
1266-
ins_str!(sym::target_abi, &sess.target.abi);
1267-
ins_str!(sym::target_arch, &sess.target.arch);
1268-
ins_str!(sym::target_endian, sess.target.endian.as_str());
1269-
ins_str!(sym::target_env, &sess.target.env);
1270-
1271-
for family in sess.target.families.as_ref() {
1272-
ins_str!(sym::target_family, family);
1273-
if family == "windows" {
1274-
ins_none!(sym::windows);
1275-
} else if family == "unix" {
1276-
ins_none!(sym::unix);
1277-
}
1278-
}
1279-
1280-
// `target_has_atomic*`
1281-
let layout = sess.target.parse_data_layout().unwrap_or_else(|err| {
1282-
sess.dcx().emit_fatal(err);
1283-
});
1284-
let mut has_atomic = false;
1285-
for (i, align) in [
1286-
(8, layout.i8_align.abi),
1287-
(16, layout.i16_align.abi),
1288-
(32, layout.i32_align.abi),
1289-
(64, layout.i64_align.abi),
1290-
(128, layout.i128_align.abi),
1291-
] {
1292-
if i >= sess.target.min_atomic_width() && i <= sess.target.max_atomic_width() {
1293-
if !has_atomic {
1294-
has_atomic = true;
1295-
if sess.is_nightly_build() {
1296-
if sess.target.atomic_cas {
1297-
ins_none!(sym::target_has_atomic);
1298-
}
1299-
ins_none!(sym::target_has_atomic_load_store);
1300-
}
1301-
}
1302-
let mut insert_atomic = |sym, align: Align| {
1303-
if sess.target.atomic_cas {
1304-
ins_sym!(sym::target_has_atomic, sym);
1305-
}
1306-
if align.bits() == i {
1307-
ins_sym!(sym::target_has_atomic_equal_alignment, sym);
1308-
}
1309-
ins_sym!(sym::target_has_atomic_load_store, sym);
1310-
};
1311-
insert_atomic(sym::integer(i), align);
1312-
if sess.target.pointer_width as u64 == i {
1313-
insert_atomic(sym::ptr, layout.pointer_align.abi);
1314-
}
1315-
}
1316-
}
1317-
1318-
ins_str!(sym::target_os, &sess.target.os);
1319-
ins_sym!(sym::target_pointer_width, sym::integer(sess.target.pointer_width));
1320-
1321-
if sess.opts.unstable_opts.has_thread_local.unwrap_or(sess.target.has_thread_local) {
1322-
ins_none!(sym::target_thread_local);
1323-
}
1324-
1325-
ins_str!(sym::target_vendor, &sess.target.vendor);
1326-
1327-
// If the user wants a test runner, then add the test cfg.
1328-
if sess.is_test_crate() {
1329-
ins_none!(sym::test);
1330-
}
1331-
1332-
ret
1333-
}
1334-
1335-
/// The parsed `--cfg` options that define the compilation environment of the
1336-
/// crate, used to drive conditional compilation.
1337-
///
1338-
/// An `FxIndexSet` is used to ensure deterministic ordering of error messages
1339-
/// relating to `--cfg`.
1340-
pub type Cfg = FxIndexSet<(Symbol, Option<Symbol>)>;
1341-
1342-
/// The parsed `--check-cfg` options.
1343-
#[derive(Default)]
1344-
pub struct CheckCfg {
1345-
/// Is well known names activated
1346-
pub exhaustive_names: bool,
1347-
/// Is well known values activated
1348-
pub exhaustive_values: bool,
1349-
/// All the expected values for a config name
1350-
pub expecteds: FxHashMap<Symbol, ExpectedValues<Symbol>>,
1351-
/// Well known names (only used for diagnostics purposes)
1352-
pub well_known_names: FxHashSet<Symbol>,
1353-
}
1354-
1355-
pub enum ExpectedValues<T> {
1356-
Some(FxHashSet<Option<T>>),
1357-
Any,
1358-
}
1359-
1360-
impl<T: Eq + Hash> ExpectedValues<T> {
1361-
fn insert(&mut self, value: T) -> bool {
1362-
match self {
1363-
ExpectedValues::Some(expecteds) => expecteds.insert(Some(value)),
1364-
ExpectedValues::Any => false,
1365-
}
1366-
}
1367-
}
1368-
1369-
impl<T: Eq + Hash> Extend<T> for ExpectedValues<T> {
1370-
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1371-
match self {
1372-
ExpectedValues::Some(expecteds) => expecteds.extend(iter.into_iter().map(Some)),
1373-
ExpectedValues::Any => {}
1374-
}
1375-
}
1376-
}
1377-
1378-
impl<'a, T: Eq + Hash + Copy + 'a> Extend<&'a T> for ExpectedValues<T> {
1379-
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
1380-
match self {
1381-
ExpectedValues::Some(expecteds) => expecteds.extend(iter.into_iter().map(|a| Some(*a))),
1382-
ExpectedValues::Any => {}
1383-
}
1384-
}
1385-
}
1386-
1387-
impl CheckCfg {
1388-
pub fn fill_well_known(&mut self, current_target: &Target) {
1389-
if !self.exhaustive_values && !self.exhaustive_names {
1390-
return;
1391-
}
1392-
1393-
let no_values = || {
1394-
let mut values = FxHashSet::default();
1395-
values.insert(None);
1396-
ExpectedValues::Some(values)
1397-
};
1398-
1399-
let empty_values = || {
1400-
let values = FxHashSet::default();
1401-
ExpectedValues::Some(values)
1402-
};
1403-
1404-
macro_rules! ins {
1405-
($name:expr, $values:expr) => {{
1406-
self.well_known_names.insert($name);
1407-
self.expecteds.entry($name).or_insert_with($values)
1408-
}};
1409-
}
1410-
1411-
// Symbols are inserted in alphabetical order as much as possible.
1412-
// The exceptions are where control flow forces things out of order.
1413-
//
1414-
// NOTE: This should be kept in sync with `default_configuration`.
1415-
// Note that symbols inserted conditionally in `default_configuration`
1416-
// are inserted unconditionally here.
1417-
//
1418-
// When adding a new config here you should also update
1419-
// `tests/ui/check-cfg/well-known-values.rs`.
1420-
//
1421-
// Don't forget to update `src/doc/unstable-book/src/compiler-flags/check-cfg.md`
1422-
// in the unstable book as well!
1423-
1424-
ins!(sym::debug_assertions, no_values);
1425-
1426-
// These four are never set by rustc, but we set them anyway: they
1427-
// should not trigger a lint because `cargo clippy`, `cargo doc`,
1428-
// `cargo test` and `cargo miri run` (respectively) can set them.
1429-
ins!(sym::clippy, no_values);
1430-
ins!(sym::doc, no_values);
1431-
ins!(sym::doctest, no_values);
1432-
ins!(sym::miri, no_values);
1433-
1434-
ins!(sym::overflow_checks, no_values);
1435-
1436-
ins!(sym::panic, empty_values).extend(&PanicStrategy::all());
1437-
1438-
ins!(sym::proc_macro, no_values);
1439-
1440-
ins!(sym::relocation_model, empty_values).extend(RelocModel::all());
1441-
1442-
let sanitize_values = SanitizerSet::all()
1443-
.into_iter()
1444-
.map(|sanitizer| Symbol::intern(sanitizer.as_str().unwrap()));
1445-
ins!(sym::sanitize, empty_values).extend(sanitize_values);
1446-
1447-
ins!(sym::sanitizer_cfi_generalize_pointers, no_values);
1448-
ins!(sym::sanitizer_cfi_normalize_integers, no_values);
1449-
1450-
ins!(sym::target_feature, empty_values).extend(
1451-
rustc_target::target_features::all_known_features()
1452-
.map(|(f, _sb)| f)
1453-
.chain(rustc_target::target_features::RUSTC_SPECIFIC_FEATURES.iter().cloned())
1454-
.map(Symbol::intern),
1455-
);
1456-
1457-
// sym::target_*
1458-
{
1459-
const VALUES: [&Symbol; 8] = [
1460-
&sym::target_abi,
1461-
&sym::target_arch,
1462-
&sym::target_endian,
1463-
&sym::target_env,
1464-
&sym::target_family,
1465-
&sym::target_os,
1466-
&sym::target_pointer_width,
1467-
&sym::target_vendor,
1468-
];
1469-
1470-
// Initialize (if not already initialized)
1471-
for &e in VALUES {
1472-
if !self.exhaustive_values {
1473-
ins!(e, || ExpectedValues::Any);
1474-
} else {
1475-
ins!(e, empty_values);
1476-
}
1477-
}
1478-
1479-
if self.exhaustive_values {
1480-
// Get all values map at once otherwise it would be costly.
1481-
// (8 values * 220 targets ~= 1760 times, at the time of writing this comment).
1482-
let [
1483-
values_target_abi,
1484-
values_target_arch,
1485-
values_target_endian,
1486-
values_target_env,
1487-
values_target_family,
1488-
values_target_os,
1489-
values_target_pointer_width,
1490-
values_target_vendor,
1491-
] = self
1492-
.expecteds
1493-
.get_many_mut(VALUES)
1494-
.expect("unable to get all the check-cfg values buckets");
1495-
1496-
for target in TARGETS
1497-
.iter()
1498-
.map(|target| Target::expect_builtin(&TargetTriple::from_triple(target)))
1499-
.chain(iter::once(current_target.clone()))
1500-
{
1501-
values_target_abi.insert(Symbol::intern(&target.options.abi));
1502-
values_target_arch.insert(Symbol::intern(&target.arch));
1503-
values_target_endian.insert(Symbol::intern(target.options.endian.as_str()));
1504-
values_target_env.insert(Symbol::intern(&target.options.env));
1505-
values_target_family.extend(
1506-
target.options.families.iter().map(|family| Symbol::intern(family)),
1507-
);
1508-
values_target_os.insert(Symbol::intern(&target.options.os));
1509-
values_target_pointer_width.insert(sym::integer(target.pointer_width));
1510-
values_target_vendor.insert(Symbol::intern(&target.options.vendor));
1511-
}
1512-
}
1513-
}
1514-
1515-
let atomic_values = &[
1516-
sym::ptr,
1517-
sym::integer(8usize),
1518-
sym::integer(16usize),
1519-
sym::integer(32usize),
1520-
sym::integer(64usize),
1521-
sym::integer(128usize),
1522-
];
1523-
for sym in [
1524-
sym::target_has_atomic,
1525-
sym::target_has_atomic_equal_alignment,
1526-
sym::target_has_atomic_load_store,
1527-
] {
1528-
ins!(sym, no_values).extend(atomic_values);
1529-
}
1530-
1531-
ins!(sym::target_thread_local, no_values);
1532-
1533-
ins!(sym::test, no_values);
1534-
1535-
ins!(sym::unix, no_values);
1536-
ins!(sym::windows, no_values);
1537-
}
1538-
}
1539-
15401204
pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
15411205
// Combine the configuration requested by the session (command line) with
15421206
// some default and generated configuration items.
1543-
user_cfg.extend(default_configuration(sess));
1207+
user_cfg.extend(cfg::default_configuration(sess));
15441208
user_cfg
15451209
}
15461210

0 commit comments

Comments
 (0)