diff --git a/libs/error-stack/Cargo.toml b/libs/error-stack/Cargo.toml index cb27231c36e..f97c70ced5e 100644 --- a/libs/error-stack/Cargo.toml +++ b/libs/error-stack/Cargo.toml @@ -49,7 +49,7 @@ thiserror = { workspace = true } rustc_version = { workspace = true } [features] -default = ["std", "backtrace", "unstable", "futures"] +default = ["std", "backtrace"] std = ["anyhow?/std"] # Enables support for `Error` backtrace = ["std"] # Enables automatic capturing of `Backtrace`s (requires Rust 1.65+) diff --git a/libs/error-stack/src/sink.rs b/libs/error-stack/src/sink.rs index 7ba191239d7..7eb37795a1b 100644 --- a/libs/error-stack/src/sink.rs +++ b/libs/error-stack/src/sink.rs @@ -19,16 +19,27 @@ use crate::Report; /// This runtime check complements the compile-time `#[must_use]` attribute, /// providing a more robust mechanism to prevent `ReportSink` not being consumed. #[derive(Debug, Default)] -enum Bomb { +enum BombState { Panic, #[default] Warn, Defused, } +#[derive(Debug, Default)] +struct Bomb(BombState); + impl Bomb { + const fn panic() -> Self { + Self(BombState::Panic) + } + + const fn warn() -> Self { + Self(BombState::Warn) + } + fn defuse(&mut self) { - *self = Self::Defused; + self.0 = BombState::Defused; } } @@ -39,13 +50,13 @@ impl Drop for Bomb { return; } - match self { - Self::Panic => panic!("ReportSink was dropped without being consumed"), + match self.0 { + BombState::Panic => panic!("ReportSink was dropped without being consumed"), #[allow(clippy::print_stderr)] - Self::Warn => { + BombState::Warn => { eprintln!("ReportSink was dropped without being consumed"); } - Self::Defused => {} + BombState::Defused => {} } } } @@ -113,7 +124,7 @@ impl ReportSink { pub const fn new() -> Self { Self { report: None, - bomb: Bomb::Warn, + bomb: Bomb::warn(), } } @@ -123,7 +134,7 @@ impl ReportSink { pub const fn new_armed() -> Self { Self { report: None, - bomb: Bomb::Panic, + bomb: Bomb::panic(), } } @@ -301,7 +312,8 @@ impl Try for ReportSink { } } - fn branch(self) -> core::ops::ControlFlow { + fn branch(mut self) -> core::ops::ControlFlow { + self.bomb.defuse(); self.report.map_or( core::ops::ControlFlow::Continue(()), // |report| core::ops::ControlFlow::Break(Err(report)), @@ -459,12 +471,12 @@ mod test { let report = sink().expect_err("should have failed"); let contexts: BTreeSet<_> = report.current_contexts().collect(); - assert_eq!(contexts.len(), 2); + assert_eq!(contexts.len(), 1); assert!(contexts.contains(&TestError(0))); } #[test] - #[should_panic(expected = "must be consumed")] + #[should_panic(expected = "without being consumed")] fn panic_on_unused() { #[allow(clippy::unnecessary_wraps)] fn sink() -> Result<(), Report<[TestError]>> { diff --git a/libs/error-stack/tests/ui/macro_invalid_args.stderr b/libs/error-stack/tests/ui/macro_invalid_args.stderr index 15e42dd26a5..83eacea6057 100644 --- a/libs/error-stack/tests/ui/macro_invalid_args.stderr +++ b/libs/error-stack/tests/ui/macro_invalid_args.stderr @@ -19,7 +19,7 @@ error: unexpected end of macro invocation note: while trying to match meta-variable `$err:expr` --> src/macros.rs | - | ($err:expr $(,)?) => {{ + | ($err:expr) => {{ | ^^^^^^^^^ error: unexpected end of macro invocation