diff --git a/build.rs b/build.rs index 129592d..56d1b88 100644 --- a/build.rs +++ b/build.rs @@ -1,70 +1,111 @@ +use std::fmt::Display; + use autocfg::AutoCfg; extern crate autocfg; fn main() { let ac = autocfg::new(); - stable_feature(&ac, "assert_matches"); - assert_matches_in_module(&ac); - assert_matches_in_root(&ac); - stable_feature(&ac, "let_chains"); + ac.emit_unstable_feature("assert_matches"); + AssertMatchesLocation::emit_possibilities(); + if let Some(location) = ac.assert_matches_location() { + autocfg::emit(&location.to_string()) + } - stable_feature(&ac, "if_let_guard"); -} + ac.emit_unstable_feature("let_chains"); -fn stable_feature(ac: &AutoCfg, feature: &'static str) { - let cfg = format!("stable_{feature}"); - let deny = format!( - r#" - #![deny(stable_features)] - #![feature({feature})] - "# - ); - - let allow = format!( - r#" - #![allow(stable_features)] - #![feature({feature})] - "# - ); - - autocfg::emit_possibility(&cfg); - if ac.probe_raw(&deny).is_err() && ac.probe_raw(&allow).is_ok() { - autocfg::emit(&cfg); - } + ac.emit_unstable_feature("if_let_guard"); } -fn assert_matches_in_root(ac: &AutoCfg) { - let cfg = "assert_matches_in_root"; - let code = r#" - #![allow(stable_features)] - #![feature(assert_matches)] - use std::assert_matches; +/// Location of assert_matches!() macro. Stabilisation was reverted at last minute +/// on 2026-04-10, leaving the macro in the new planned location. +enum AssertMatchesLocation { + /// Macro is at `std::assert_matches` + Root, + /// Macro is at `std::assert_matches::assert_matches` + Module, +} - fn main() { - assert_matches!(Some(4), Some(_)); +impl Display for AssertMatchesLocation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AssertMatchesLocation::Root => write!(f, "assert_matches_in_root"), + AssertMatchesLocation::Module => write!(f, "assert_matches_in_module"), + } } - "#; - autocfg::emit_possibility(cfg); - if ac.probe_raw(code).is_ok() { - autocfg::emit(cfg); +} + +impl AssertMatchesLocation { + fn emit_possibilities() { + autocfg::emit_possibility(&AssertMatchesLocation::Root.to_string()); + autocfg::emit_possibility(&AssertMatchesLocation::Module.to_string()); } } -fn assert_matches_in_module(ac: &AutoCfg) { - let cfg = "assert_matches_in_module"; - let code = r#" - #![allow(stable_features)] - #![feature(assert_matches)] - use std::assert_matches::assert_matches; +trait Nightly { + /// Identify whether a an experimental feature flag is available _and_ required on nightly. + /// Always fails if feature flags are unavailable. + /// + /// ## Usage: + /// To be used at top-level crate via `#![cfg_attr(unstable_foo, feature(foo))]` + fn emit_unstable_feature(&self, feature: &'static str); - fn main() { - assert_matches!(Some(4), Some(_)); + /// Location of assert_matches!() macro. Stabilisation was reverted at last minute + /// on 2026-04-10, leaving the macro in the new planned location. + /// + /// #Recommended usage + /// ``` + /// AssertMatchesLocation::emit_possibilities(); + /// if let Some(location) = ac.assert_matches_location() { + /// autocfg::emit(&location.to_string()) + /// } + /// ``` + fn assert_matches_location(&self) -> Option; +} + +impl Nightly for AutoCfg { + fn emit_unstable_feature(&self, feature: &'static str) { + let cfg = format!("unstable_{feature}"); + let code = format!( + r#" + #![deny(stable_features)] + #![feature({feature})] + "# + ); + autocfg::emit_possibility(&cfg); + if self.probe_raw(&code).is_ok() { + autocfg::emit(&cfg); + } } - "#; - autocfg::emit_possibility(cfg); - if ac.probe_raw(code).is_ok() { - autocfg::emit(cfg); + + fn assert_matches_location(&self) -> Option { + let in_root = r#" + #![allow(stable_features)] + #![feature(assert_matches)] + use std::assert_matches; + + fn main() { + assert_matches!(Some(4), Some(_)); + } + "#; + + let in_module = r#" + #![allow(stable_features)] + #![feature(assert_matches)] + use std::assert_matches::assert_matches; + + fn main() { + assert_matches!(Some(4), Some(_)); + } + "#; + + if self.probe_raw(in_root).is_ok() { + Some(AssertMatchesLocation::Root) + } else if self.probe_raw(in_module).is_ok() { + Some(AssertMatchesLocation::Module) + } else { + None + } } } diff --git a/src/lib.rs b/src/lib.rs index a98c4af..6e8601c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ -#![cfg_attr(not(stable_if_let_guard), feature(if_let_guard))] -#![cfg_attr(not(stable_let_chains), feature(let_chains))] +#![cfg_attr(unstable_if_let_guard, feature(if_let_guard))] +#![cfg_attr(unstable_let_chains, feature(let_chains))] #![feature(never_type)] //! Provides a derive macro for [Try] & optionally [Try_ConvertResult] for interconversion with diff --git a/tests/test_usage.rs b/tests/test_usage.rs index 0cd4d90..f3b0605 100644 --- a/tests/test_usage.rs +++ b/tests/test_usage.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(stable_assert_matches), feature(assert_matches))] +#![cfg_attr(unstable_assert_matches, feature(assert_matches))] #![feature(iterator_try_collect)] #![feature(never_type)] #![feature(try_trait_v2)]