Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 91 additions & 50 deletions build.rs
Original file line number Diff line number Diff line change
@@ -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,
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
}

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<AssertMatchesLocation>;
}

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<AssertMatchesLocation> {
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
}
}
}
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/test_usage.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down
Loading