diff --git a/crates/std_detect/Cargo.toml b/crates/std_detect/Cargo.toml index acfcc116f4..857d8a5b9b 100644 --- a/crates/std_detect/Cargo.toml +++ b/crates/std_detect/Cargo.toml @@ -31,6 +31,7 @@ auxv = "0.3.3" cupid = "0.6.0" [features] -default = [ "std_detect_dlsym_getauxval", "std_detect_file_io" ] +default = [ "std_detect_dlsym_getauxval", "std_detect_file_io", "std_detect_env_override" ] std_detect_file_io = [] -std_detect_dlsym_getauxval = [ "libc" ] \ No newline at end of file +std_detect_dlsym_getauxval = [ "libc" ] +std_detect_env_override = [] diff --git a/crates/std_detect/src/detect/cache.rs b/crates/std_detect/src/detect/cache.rs index 0056cd3026..b4d942b2b3 100644 --- a/crates/std_detect/src/detect/cache.rs +++ b/crates/std_detect/src/detect/cache.rs @@ -162,6 +162,26 @@ impl Cache { self.1.store(hi, Ordering::Relaxed); } } +cfg_if! { + if #[cfg(feature = "std_detect_env_override")] { + fn env_override(mut value: Initializer) -> Initializer { + if let Ok(disable) = crate::env::var("RUST_STD_DETECT_UNSTABLE") { + for v in disable.split(" ") { + let _ = super::Feature::from_str(v).map(|v| value.unset(v as u32)); + } + value + } else { + value + } + } + } else { + #[inline] + fn env_override(value: Initializer) -> Initializer { + value + } + } +} + /// Tests the `bit` of the storage. If the storage has not been initialized, /// initializes it with the result of `f()`. @@ -171,13 +191,17 @@ impl Cache { /// /// It uses the `Feature` variant to index into this variable as a bitset. If /// the bit is set, the feature is enabled, and otherwise it is disabled. +/// +/// If the feature `std_detect_env_override` is enabled looks for the env +/// variable `RUST_STD_DETECT_UNSTABLE` and uses its its content to disable +/// Features that would had been otherwise detected. #[inline] pub(crate) fn test(bit: u32, f: F) -> bool where F: FnOnce() -> Initializer, { if CACHE.is_uninitialized() { - CACHE.initialize(f()); + CACHE.initialize(env_override(f())); } CACHE.test(bit) } diff --git a/crates/std_detect/src/detect/macros.rs b/crates/std_detect/src/detect/macros.rs index 750cf50aa7..c9200d2f1f 100644 --- a/crates/std_detect/src/detect/macros.rs +++ b/crates/std_detect/src/detect/macros.rs @@ -69,6 +69,12 @@ macro_rules! features { Feature::_last => unreachable!(), } } + pub fn from_str(s: &str) -> Result { + match s { + $($feature_lit => Ok(Feature::$feature),)* + _ => Err(()) + } + } } /// Each function performs run-time feature detection for a single diff --git a/crates/std_detect/src/lib.rs b/crates/std_detect/src/lib.rs index 7737719c3b..9f4b9918e7 100644 --- a/crates/std_detect/src/lib.rs +++ b/crates/std_detect/src/lib.rs @@ -24,12 +24,23 @@ extern crate cfg_if; cfg_if! { - if #[cfg(feature = "std_detect_file_io")] { + if #[cfg(all(feature = "std_detect_file_io", feature = "std_detect_env_override"))] { + #[cfg_attr(test, macro_use(println))] + extern crate std; + + #[allow(unused_imports)] + use std::{arch, env, fs, io, mem, sync}; + } else if #[cfg(feature = "std_detect_file_io")] { #[cfg_attr(test, macro_use(println))] extern crate std; #[allow(unused_imports)] use std::{arch, fs, io, mem, sync}; + } else if #[cfg(feature = "std_detect_env_override")] { + #[cfg_attr(test, macro_use(println))] + extern crate std; + + use std::env; } else { #[cfg(test)] #[macro_use(println)]