From 51006700652a0ea5f21de01f8d724f5bd340627c Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 5 Nov 2024 20:31:40 +0100 Subject: [PATCH 1/3] Add ability to declare a feature without cfg checking This is necessary to avoid `unexpected_cfgs` warnings for unexpected/ missing target features, in user code. --- crates/std_detect/src/detect/macros.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/std_detect/src/detect/macros.rs b/crates/std_detect/src/detect/macros.rs index 5321ef2252..f2cc711812 100644 --- a/crates/std_detect/src/detect/macros.rs +++ b/crates/std_detect/src/detect/macros.rs @@ -9,6 +9,9 @@ macro_rules! detect_feature { $(cfg!(target_feature = $target_feature_lit) ||)* $crate::detect::__is_feature_detected::$feature() }; + ($feature:tt, $feature_lit:tt, without cfg check: true) => { + $crate::detect::__is_feature_detected::$feature() + }; } #[allow(unused)] @@ -21,6 +24,7 @@ macro_rules! features { $(@BIND_FEATURE_NAME: $bind_feature:tt; $feature_impl:tt; $(#[$deprecate_attr:meta];)?)* $(@NO_RUNTIME_DETECTION: $nort_feature:tt; )* $(@FEATURE: #[$stability_attr:meta] $feature:ident: $feature_lit:tt; + $(without cfg check: $feature_cfg_check:literal;)? $(implied by target_features: [$($target_feature_lit:tt),*];)? $(#[$feature_comment:meta])*)* ) => { @@ -32,7 +36,7 @@ macro_rules! features { macro_rules! $macro_name { $( ($feature_lit) => { - $crate::detect_feature!($feature, $feature_lit $(: $($target_feature_lit),*)?) + $crate::detect_feature!($feature, $feature_lit $(, without cfg check: $feature_cfg_check)? $(: $($target_feature_lit),*)?) }; )* $( From d25fa4e2f7ef740a3aea18c9f5a3bca2c5e181f5 Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 5 Nov 2024 20:38:57 +0100 Subject: [PATCH 2/3] Mark feature with missing corresponding target feature cfgs as such Computed by diffing of: $ rg "[ ]+@FEATURE: .*: \"(.*)\";" -r '$1' --no-filename \ crates/std_detect/src/detect/ | sort | uniq With (from the main Rust repo[^1]): $ rg "target_feature" tests/ui/check-cfg/well-known-values.stderr [^1]: https://github.com/rust-lang/rust/blob/e8c698bb3bdc121ac7f65919bd16d22f6567a3f1/tests/ui/check-cfg/well-known-values.stderr#L177 --- crates/std_detect/src/detect/arch/aarch64.rs | 1 + crates/std_detect/src/detect/arch/arm.rs | 1 + crates/std_detect/src/detect/arch/powerpc.rs | 1 + .../std_detect/src/detect/arch/powerpc64.rs | 1 + crates/std_detect/src/detect/arch/riscv.rs | 19 +++++++++++++++++++ crates/std_detect/src/detect/arch/x86.rs | 4 ++++ 6 files changed, 27 insertions(+) diff --git a/crates/std_detect/src/detect/arch/aarch64.rs b/crates/std_detect/src/detect/arch/aarch64.rs index 925b73eccb..13570a25c1 100644 --- a/crates/std_detect/src/detect/arch/aarch64.rs +++ b/crates/std_detect/src/detect/arch/aarch64.rs @@ -160,6 +160,7 @@ features! { @FEATURE: #[unstable(feature = "stdarch_aarch64_feature_detection", issue = "127764")] fp8fma: "fp8fma"; /// FEAT_FP8FMA (F8FMA Instructions) @FEATURE: #[unstable(feature = "stdarch_aarch64_feature_detection", issue = "127764")] fpmr: "fpmr"; + without cfg check: true; /// FEAT_FPMR (Special-purpose AArch64-FPMR register) @FEATURE: #[stable(feature = "simd_aarch64", since = "1.60.0")] frintts: "frintts"; /// FEAT_FRINTTS (float to integer rounding instructions) diff --git a/crates/std_detect/src/detect/arch/arm.rs b/crates/std_detect/src/detect/arch/arm.rs index 50e77fde59..c3c8883ce3 100644 --- a/crates/std_detect/src/detect/arch/arm.rs +++ b/crates/std_detect/src/detect/arch/arm.rs @@ -14,6 +14,7 @@ features! { @FEATURE: #[unstable(feature = "stdarch_arm_feature_detection", issue = "111190")] neon: "neon"; /// ARM Advanced SIMD (NEON) - Aarch32 @FEATURE: #[unstable(feature = "stdarch_arm_feature_detection", issue = "111190")] pmull: "pmull"; + without cfg check: true; /// Polynomial Multiply @FEATURE: #[unstable(feature = "stdarch_arm_feature_detection", issue = "111190")] crc: "crc"; /// CRC32 (Cyclic Redundancy Check) diff --git a/crates/std_detect/src/detect/arch/powerpc.rs b/crates/std_detect/src/detect/arch/powerpc.rs index fc2ac8963f..85ec101f18 100644 --- a/crates/std_detect/src/detect/arch/powerpc.rs +++ b/crates/std_detect/src/detect/arch/powerpc.rs @@ -12,5 +12,6 @@ features! { @FEATURE: #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] vsx: "vsx"; /// VSX @FEATURE: #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] power8: "power8"; + without cfg check: true; /// Power8 } diff --git a/crates/std_detect/src/detect/arch/powerpc64.rs b/crates/std_detect/src/detect/arch/powerpc64.rs index 579bdc50ca..813429c40c 100644 --- a/crates/std_detect/src/detect/arch/powerpc64.rs +++ b/crates/std_detect/src/detect/arch/powerpc64.rs @@ -12,5 +12,6 @@ features! { @FEATURE: #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] vsx: "vsx"; /// VSX @FEATURE: #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] power8: "power8"; + without cfg check: true; /// Power8 } diff --git a/crates/std_detect/src/detect/arch/riscv.rs b/crates/std_detect/src/detect/arch/riscv.rs index ea6a5e65b4..0980406a7a 100644 --- a/crates/std_detect/src/detect/arch/riscv.rs +++ b/crates/std_detect/src/detect/arch/riscv.rs @@ -90,28 +90,36 @@ features! { /// [ISA manual]: https://github.com/riscv/riscv-isa-manual/ #[stable(feature = "riscv_ratified", since = "1.76.0")] @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] rv32i: "rv32i"; + without cfg check: true; /// RV32I Base Integer Instruction Set @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zifencei: "zifencei"; + without cfg check: true; /// "Zifencei" Instruction-Fetch Fence @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zihintpause: "zihintpause"; + without cfg check: true; /// "Zihintpause" Pause Hint @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] rv64i: "rv64i"; + without cfg check: true; /// RV64I Base Integer Instruction Set @FEATURE: #[stable(feature = "riscv_ratified", since = "1.76.0")] m: "m"; /// "M" Standard Extension for Integer Multiplication and Division @FEATURE: #[stable(feature = "riscv_ratified", since = "1.76.0")] a: "a"; /// "A" Standard Extension for Atomic Instructions @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zicsr: "zicsr"; + without cfg check: true; /// "Zicsr", Control and Status Register (CSR) Instructions @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zicntr: "zicntr"; + without cfg check: true; /// "Zicntr", Standard Extension for Base Counters and Timers @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zihpm: "zihpm"; + without cfg check: true; /// "Zihpm", Standard Extension for Hardware Performance Counters @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] f: "f"; /// "F" Standard Extension for Single-Precision Floating-Point @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] d: "d"; /// "D" Standard Extension for Double-Precision Floating-Point @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] q: "q"; + without cfg check: true; /// "Q" Standard Extension for Quad-Precision Floating-Point @FEATURE: #[stable(feature = "riscv_ratified", since = "1.76.0")] c: "c"; /// "C" Standard Extension for Compressed Instructions @@ -125,34 +133,45 @@ features! { @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zhinxmin: "zhinxmin"; /// "Zhinxmin" Standard Extension for Minimal Half-Precision Floating-Point in Integer Registers @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] ztso: "ztso"; + without cfg check: true; /// "Ztso" Standard Extension for Total Store Ordering @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] rv32e: "rv32e"; + without cfg check: true; /// RV32E Base Integer Instruction Set @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] rv128i: "rv128i"; + without cfg check: true; /// RV128I Base Integer Instruction Set @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zfh: "zfh"; /// "Zfh" Standard Extension for 16-Bit Half-Precision Floating-Point @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zfhmin: "zfhmin"; /// "Zfhmin" Standard Extension for Minimal Half-Precision Floating-Point Support @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] j: "j"; + without cfg check: true; /// "J" Standard Extension for Dynamically Translated Languages @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] p: "p"; + without cfg check: true; /// "P" Standard Extension for Packed-SIMD Instructions @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] v: "v"; /// "V" Standard Extension for Vector Operations @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zam: "zam"; + without cfg check: true; /// "Zam" Standard Extension for Misaligned Atomics @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] s: "s"; + without cfg check: true; /// Supervisor-Level ISA @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] svnapot: "svnapot"; + without cfg check: true; /// "Svnapot" Standard Extension for NAPOT Translation Contiguity @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] svpbmt: "svpbmt"; + without cfg check: true; /// "Svpbmt" Standard Extension for Page-Based Memory Types @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] svinval: "svinval"; + without cfg check: true; /// "Svinval" Standard Extension for Fine-Grained Address-Translation Cache Invalidation @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] h: "h"; + without cfg check: true; /// Hypervisor Extension @FEATURE: #[stable(feature = "riscv_ratified", since = "1.76.0")] zba: "zba"; diff --git a/crates/std_detect/src/detect/arch/x86.rs b/crates/std_detect/src/detect/arch/x86.rs index 2890c7ee2f..891fc427db 100644 --- a/crates/std_detect/src/detect/arch/x86.rs +++ b/crates/std_detect/src/detect/arch/x86.rs @@ -123,8 +123,10 @@ features! { @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] rdseed: "rdseed"; /// RDSEED @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] tsc: "tsc"; + without cfg check: true; /// TSC (Time Stamp Counter) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] mmx: "mmx"; + without cfg check: true; /// MMX (MultiMedia eXtensions) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] sse: "sse"; /// SSE (Streaming SIMD Extensions) @@ -157,8 +159,10 @@ features! { @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512cd: "avx512cd" ; /// AVX-512 CD (Conflict Detection Instructions) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512er: "avx512er"; + without cfg check: true; /// AVX-512 ER (Expo nential and Reciprocal Instructions) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512pf: "avx512pf"; + without cfg check: true; /// AVX-512 PF (Prefetch Instructions) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512bw: "avx512bw"; /// AVX-512 BW (Byte and Word Instructions) From ccff009262e17e7fccc14954d1e3908366ab46f3 Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 7 Nov 2024 00:28:43 +0100 Subject: [PATCH 3/3] Add compile-time tests against unexpected target features cfgs --- crates/std_detect/src/detect/macros.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/crates/std_detect/src/detect/macros.rs b/crates/std_detect/src/detect/macros.rs index f2cc711812..38c8b8068f 100644 --- a/crates/std_detect/src/detect/macros.rs +++ b/crates/std_detect/src/detect/macros.rs @@ -14,6 +14,21 @@ macro_rules! detect_feature { }; } +#[allow(unused_macros, reason = "it's used in the features! macro below")] +macro_rules! check_cfg_feature { + ($feature:tt, $feature_lit:tt) => { + check_cfg_feature!($feature, $feature_lit : $feature_lit) + }; + ($feature:tt, $feature_lit:tt : $($target_feature_lit:tt),*) => { + $(cfg!(target_feature = $target_feature_lit);)* + }; + ($feature:tt, $feature_lit:tt, without cfg check: $feature_cfg_check:literal) => { + // FIXME: Enable once rust-lang/rust#132577 hit's nightly + // #[expect(unexpected_cfgs, reason = $feature_lit)] + // { cfg!(target_feature = $feature_lit) } + }; +} + #[allow(unused)] macro_rules! features { ( @@ -117,6 +132,15 @@ macro_rules! features { }; } + #[test] + #[deny(unexpected_cfgs)] + #[deny(unfulfilled_lint_expectations)] + fn unexpected_cfgs() { + $( + check_cfg_feature!($feature, $feature_lit $(, without cfg check: $feature_cfg_check)? $(: $($target_feature_lit),*)?); + )* + } + /// Each variant denotes a position in a bitset for a particular feature. /// /// PLEASE: do not use this, it is an implementation detail subject