Skip to content

Commit c8ff668

Browse files
authored
Rollup merge of rust-lang#94362 - Urgau:check-cfg-values, r=petrochenkov
Add well known values to `--check-cfg` implementation This pull-request adds well known values for the well known names via `--check-cfg=values()`. [RFC 3013: Checking conditional compilation at compile time](https://rust-lang.github.io/rfcs/3013-conditional-compilation-checking.html#checking-conditional-compilation-at-compile-time) doesn't define this at all, but this seems a nice improvement. The activation is done by a empty `values()` (new syntax) similar to `names()` except that `names(foo)` also activate well known names while `values(aa, "aa", "kk")` would not. As stated this use a different activation logic because well known values for the well known names are not always sufficient. In fact this is problematic for every `target_*` cfg because of non builtin targets, as the current implementation use those built-ins targets to create the list the well known values. The implementation is straight forward, first we gather (if necessary) all the values (lazily or not) and then we apply them. r? ``@petrochenkov``
2 parents 1b14fd3 + 4aa92af commit c8ff668

File tree

8 files changed

+207
-11
lines changed

8 files changed

+207
-11
lines changed

Diff for: compiler/rustc_interface/src/interface.rs

+3
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
207207
"`values()` first argument must be a simple identifer"
208208
);
209209
}
210+
} else if args.is_empty() {
211+
cfg.well_known_values = true;
212+
continue 'specs;
210213
}
211214
}
212215
}

Diff for: compiler/rustc_session/src/config.rs

+110-6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_data_structures::impl_stable_hash_via_hash;
1313

1414
use rustc_target::abi::{Align, TargetDataLayout};
1515
use rustc_target::spec::{LinkerFlavor, SplitDebuginfo, Target, TargetTriple, TargetWarnings};
16+
use rustc_target::spec::{PanicStrategy, SanitizerSet, TARGETS};
1617

1718
use rustc_serialize::json;
1819

@@ -1025,13 +1026,19 @@ pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig
10251026
pub struct CheckCfg<T = String> {
10261027
/// The set of all `names()`, if None no name checking is performed
10271028
pub names_valid: Option<FxHashSet<T>>,
1029+
/// Is well known values activated
1030+
pub well_known_values: bool,
10281031
/// The set of all `values()`
10291032
pub values_valid: FxHashMap<T, FxHashSet<T>>,
10301033
}
10311034

10321035
impl<T> Default for CheckCfg<T> {
10331036
fn default() -> Self {
1034-
CheckCfg { names_valid: Default::default(), values_valid: Default::default() }
1037+
CheckCfg {
1038+
names_valid: Default::default(),
1039+
values_valid: Default::default(),
1040+
well_known_values: false,
1041+
}
10351042
}
10361043
}
10371044

@@ -1047,6 +1054,7 @@ impl<T> CheckCfg<T> {
10471054
.iter()
10481055
.map(|(a, b)| (f(a), b.iter().map(|b| f(b)).collect()))
10491056
.collect(),
1057+
well_known_values: self.well_known_values,
10501058
}
10511059
}
10521060
}
@@ -1060,8 +1068,9 @@ pub fn to_crate_check_config(cfg: CheckCfg) -> CrateCheckConfig {
10601068

10611069
impl CrateCheckConfig {
10621070
/// Fills a `CrateCheckConfig` with well-known configuration names.
1063-
pub fn fill_well_known(&mut self) {
1064-
// NOTE: This should be kept in sync with `default_configuration`
1071+
fn fill_well_known_names(&mut self) {
1072+
// NOTE: This should be kept in sync with `default_configuration` and
1073+
// `fill_well_known_values`
10651074
const WELL_KNOWN_NAMES: &[Symbol] = &[
10661075
sym::unix,
10671076
sym::windows,
@@ -1086,11 +1095,106 @@ impl CrateCheckConfig {
10861095
sym::doctest,
10871096
sym::feature,
10881097
];
1098+
1099+
// We only insert well-known names if `names()` was activated
10891100
if let Some(names_valid) = &mut self.names_valid {
1090-
for &name in WELL_KNOWN_NAMES {
1091-
names_valid.insert(name);
1092-
}
1101+
names_valid.extend(WELL_KNOWN_NAMES);
1102+
}
1103+
}
1104+
1105+
/// Fills a `CrateCheckConfig` with well-known configuration values.
1106+
fn fill_well_known_values(&mut self) {
1107+
if !self.well_known_values {
1108+
return;
10931109
}
1110+
1111+
// NOTE: This should be kept in sync with `default_configuration` and
1112+
// `fill_well_known_names`
1113+
1114+
let panic_values = &PanicStrategy::all();
1115+
1116+
let atomic_values = &[
1117+
sym::ptr,
1118+
sym::integer(8usize),
1119+
sym::integer(16usize),
1120+
sym::integer(32usize),
1121+
sym::integer(64usize),
1122+
sym::integer(128usize),
1123+
];
1124+
1125+
let sanitize_values = SanitizerSet::all()
1126+
.into_iter()
1127+
.map(|sanitizer| Symbol::intern(sanitizer.as_str().unwrap()));
1128+
1129+
// No-values
1130+
for name in [
1131+
sym::unix,
1132+
sym::windows,
1133+
sym::debug_assertions,
1134+
sym::proc_macro,
1135+
sym::test,
1136+
sym::doc,
1137+
sym::doctest,
1138+
sym::target_thread_local,
1139+
] {
1140+
self.values_valid.entry(name).or_default();
1141+
}
1142+
1143+
// Pre-defined values
1144+
self.values_valid.entry(sym::panic).or_default().extend(panic_values);
1145+
self.values_valid.entry(sym::sanitize).or_default().extend(sanitize_values);
1146+
self.values_valid.entry(sym::target_has_atomic).or_default().extend(atomic_values);
1147+
self.values_valid
1148+
.entry(sym::target_has_atomic_load_store)
1149+
.or_default()
1150+
.extend(atomic_values);
1151+
self.values_valid
1152+
.entry(sym::target_has_atomic_equal_alignment)
1153+
.or_default()
1154+
.extend(atomic_values);
1155+
1156+
// Target specific values
1157+
for target in
1158+
TARGETS.iter().map(|target| Target::expect_builtin(&TargetTriple::from_triple(target)))
1159+
{
1160+
self.values_valid
1161+
.entry(sym::target_os)
1162+
.or_default()
1163+
.insert(Symbol::intern(&target.options.os));
1164+
self.values_valid
1165+
.entry(sym::target_family)
1166+
.or_default()
1167+
.extend(target.options.families.iter().map(|family| Symbol::intern(family)));
1168+
self.values_valid
1169+
.entry(sym::target_arch)
1170+
.or_default()
1171+
.insert(Symbol::intern(&target.arch));
1172+
self.values_valid
1173+
.entry(sym::target_endian)
1174+
.or_default()
1175+
.insert(Symbol::intern(&target.options.endian.as_str()));
1176+
self.values_valid
1177+
.entry(sym::target_env)
1178+
.or_default()
1179+
.insert(Symbol::intern(&target.options.env));
1180+
self.values_valid
1181+
.entry(sym::target_abi)
1182+
.or_default()
1183+
.insert(Symbol::intern(&target.options.abi));
1184+
self.values_valid
1185+
.entry(sym::target_vendor)
1186+
.or_default()
1187+
.insert(Symbol::intern(&target.options.vendor));
1188+
self.values_valid
1189+
.entry(sym::target_pointer_width)
1190+
.or_default()
1191+
.insert(sym::integer(target.pointer_width));
1192+
}
1193+
}
1194+
1195+
pub fn fill_well_known(&mut self) {
1196+
self.fill_well_known_names();
1197+
self.fill_well_known_values();
10941198
}
10951199

10961200
/// Fills a `CrateCheckConfig` with configuration names and values that are actually active.

Diff for: compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,7 @@ symbols! {
10631063
proc_macro_path_invoc,
10641064
profiler_builtins,
10651065
profiler_runtime,
1066+
ptr,
10661067
ptr_guaranteed_eq,
10671068
ptr_guaranteed_ne,
10681069
ptr_null,

Diff for: compiler/rustc_target/src/spec/mod.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,16 @@ impl PanicStrategy {
186186
}
187187
}
188188

189-
pub fn desc_symbol(&self) -> Symbol {
189+
pub const fn desc_symbol(&self) -> Symbol {
190190
match *self {
191191
PanicStrategy::Unwind => sym::unwind,
192192
PanicStrategy::Abort => sym::abort,
193193
}
194194
}
195+
196+
pub const fn all() -> [Symbol; 2] {
197+
[Self::Abort.desc_symbol(), Self::Unwind.desc_symbol()]
198+
}
195199
}
196200

197201
impl ToJson for PanicStrategy {
@@ -614,7 +618,7 @@ impl SanitizerSet {
614618
/// Return sanitizer's name
615619
///
616620
/// Returns none if the flags is a set of sanitizers numbering not exactly one.
617-
fn as_str(self) -> Option<&'static str> {
621+
pub fn as_str(self) -> Option<&'static str> {
618622
Some(match self {
619623
SanitizerSet::ADDRESS => "address",
620624
SanitizerSet::CFI => "cfi",
@@ -2137,6 +2141,18 @@ impl Target {
21372141
))
21382142
}
21392143

2144+
/// Load a built-in target
2145+
pub fn expect_builtin(target_triple: &TargetTriple) -> Target {
2146+
match *target_triple {
2147+
TargetTriple::TargetTriple(ref target_triple) => {
2148+
load_builtin(target_triple).expect("built-in target")
2149+
}
2150+
TargetTriple::TargetPath(..) => {
2151+
panic!("built-in targets doens't support target-paths")
2152+
}
2153+
}
2154+
}
2155+
21402156
/// Search for a JSON file specifying the given target triple.
21412157
///
21422158
/// If none is found in `$RUST_TARGET_PATH`, look for a file called `target.json` inside the

Diff for: src/test/ui/check-cfg/empty-values.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
// Check that a an empty values() is rejected
1+
// Check warning for unexpected cfg value
22
//
3-
// check-fail
3+
// check-pass
44
// compile-flags: --check-cfg=values() -Z unstable-options
55

6+
#[cfg(test = "value")]
7+
//~^ WARNING unexpected `cfg` condition value
8+
pub fn f() {}
9+
610
fn main() {}

Diff for: src/test/ui/check-cfg/empty-values.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,11 @@
1-
error: invalid `--check-cfg` argument: `values()` (expected `names(name1, name2, ... nameN)` or `values(name, "value1", "value2", ... "valueN")`)
1+
warning: unexpected `cfg` condition value
2+
--> $DIR/empty-values.rs:6:7
3+
|
4+
LL | #[cfg(test = "value")]
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(unexpected_cfgs)]` on by default
8+
= note: no expected value for `test`
9+
10+
warning: 1 warning emitted
211

Diff for: src/test/ui/check-cfg/well-known-values.rs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// This test check that we lint on non well known values and that we don't lint on well known
2+
// values
3+
//
4+
// check-pass
5+
// compile-flags: --check-cfg=values() -Z unstable-options
6+
7+
#[cfg(target_os = "linuz")]
8+
//~^ WARNING unexpected `cfg` condition value
9+
fn target_os_linux_misspell() {}
10+
11+
#[cfg(target_os = "linux")]
12+
fn target_os_linux() {}
13+
14+
#[cfg(target_has_atomic = "0")]
15+
//~^ WARNING unexpected `cfg` condition value
16+
fn target_has_atomic_invalid() {}
17+
18+
#[cfg(target_has_atomic = "8")]
19+
fn target_has_atomic() {}
20+
21+
#[cfg(unix = "aa")]
22+
//~^ WARNING unexpected `cfg` condition value
23+
fn unix_with_value() {}
24+
25+
#[cfg(unix)]
26+
fn unix() {}
27+
28+
fn main() {}

Diff for: src/test/ui/check-cfg/well-known-values.stderr

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
warning: unexpected `cfg` condition value
2+
--> $DIR/well-known-values.rs:7:7
3+
|
4+
LL | #[cfg(target_os = "linuz")]
5+
| ^^^^^^^^^^^^-------
6+
| |
7+
| help: did you mean: `"linux"`
8+
|
9+
= note: `#[warn(unexpected_cfgs)]` on by default
10+
= note: expected values for `target_os` are: android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, windows
11+
12+
warning: unexpected `cfg` condition value
13+
--> $DIR/well-known-values.rs:14:7
14+
|
15+
LL | #[cfg(target_has_atomic = "0")]
16+
| ^^^^^^^^^^^^^^^^^^^^---
17+
| |
18+
| help: did you mean: `"8"`
19+
|
20+
= note: expected values for `target_has_atomic` are: 128, 16, 32, 64, 8, ptr
21+
22+
warning: unexpected `cfg` condition value
23+
--> $DIR/well-known-values.rs:21:7
24+
|
25+
LL | #[cfg(unix = "aa")]
26+
| ^^^^^^^^^^^
27+
|
28+
= note: no expected value for `unix`
29+
30+
warning: 3 warnings emitted
31+

0 commit comments

Comments
 (0)