Thanks to visit codestin.com
Credit goes to lib.rs

#cleanup #defer #macro

guarden

Zero-cost abstractions for scoped guards, deferred execution, and async task detachment

4 releases

Uses new Rust 2024

0.1.3 Apr 27, 2026
0.1.2 Apr 27, 2026
0.1.1 Apr 27, 2026
0.1.0 Apr 27, 2026

#611 in Rust patterns

Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App

7,694 downloads per month

MIT license

44KB
568 lines

guarden provides scoped guard macros for deferred cleanup and manual triggers.

The public API centers on three macros:

  • guarded! for binding a guard to a local variable that runs on Drop.
  • guard! for creating a guard value that can be triggered manually.
  • defer! as a convenience alias for guarded!.

The macros support synchronous and asynchronous bodies, explicit capture lists, and export controls for captured values.

⚠️ Critical Usage Note: Diverging Expressions

Do not use "naked" diverging expressions—such as panic!, todo!, or loop {}—as the sole content of a sync guard closure. This prevents the compiler from distinguishing between synchronous (ASYNC = false) and asynchronous (ASYNC = true) implementations, leading to a type inference error (E0277).

Technical Context

The ! (Never Type) is a bottom type that can be coerced into any other type. Because it satisfies both the () return type requirement for sync guards and the Future trait requirement for async guards, the compiler encounters an inference deadlock.

Workaround

For macros like guard! or guarded!, force the closure to resolve to () by explicitly setting the guard to sync:

let val = "critical failure".to_string();
guarded! {
    sync [val] {
        panic!("{}", val);
    }
}

guarden

guarden is the main library crate in the workspace. It re-exports the public macros for scoped cleanup and deferred execution:

  • guarded! - bind a guard to a local variable and run its body when dropped.
  • guard! - create a guard value that you can trigger manually.
  • defer! - an alias for guarded!.

The crate supports both synchronous and asynchronous bodies, explicit capture lists, and export control for captured values.

Example

use guarden::guarded;

let sink = std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0));

{
    guarded!([sink = sink.clone()] {
        sink.store(7, std::sync::atomic::Ordering::SeqCst);
    });
}

assert_eq!(sink.load(std::sync::atomic::Ordering::SeqCst), 7);

Notes

For more background and workspace-level usage, see the root README.md.

License

MIT

Dependencies

~2.3–3.5MB
~58K SLoC