scopeguard

A RAII scope guard for Rust that runs a closure on scope exit, even during a panic.

Library
Cargo
v1.2.0
564stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
34/100Needs Attention
Development Activity0
Maintenance0
Community56
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
81/100Excellent
Architecture80
Code Quality78
Innovation70
Learning Curve95

scopeguard is a small, focused Rust crate providing a RAII scope guard: a value that runs a given closure when it goes out of scope, whether that’s via normal return or an unwinding panic. It exposes the guard() function plus defer!, defer_on_unwind!, and defer_on_success! macros as shorthands for the three cleanup strategies — always, only on unwind, or only on success.

The crate is no_std compatible for its core defer!/guard functionality (requiring only core), with the unwind-detection strategies gated behind the default use_std feature. It has no runtime dependencies and is widely used as a building block by other crates (including parts of the Rust standard library ecosystem) needing deterministic cleanup semantics similar to Go’s defer or C++ destructors.

What You Get

  • The guard(value, closure) function, wrapping a value so the closure runs on drop with access to the wrapped value
  • The defer! macro for panic-safe cleanup blocks that always run when the enclosing scope exits
  • defer_on_unwind! and defer_on_success! macros to run cleanup only when a panic is unwinding or only when the scope exits normally, respectively
  • no_std support for the core guard/defer functionality when the default use_std feature is disabled

Common Use Cases

  • Ensuring a resource (file handle, lock, temporary state) is cleaned up even if a panic occurs mid-function
  • Rolling back partial state changes only when a panic unwinds through the guarded scope, via defer_on_unwind!
  • Committing a side effect (like a log message or metric) only after a block completes successfully, via defer_on_success!
  • Writing panic-safe FFI or unsafe code where deterministic cleanup on every exit path is required

Under The Hood

Architecture — the entire crate lives in a single src/lib.rs (595 lines): a ScopeGuard<T, F> struct wraps a value T and a closure F, implementing Drop to invoke the closure; three marker strategy types (Always, OnUnwind, OnSuccess) implement a shared Strategy trait whose should_run() checks std::thread::panicking() to decide whether cleanup fires, letting one Drop impl serve all three macros. Tech Stack — zero-dependency Rust, no_std-compatible for the core path (only core required), with the unwind/success strategies requiring std::thread::panicking() and therefore gated behind the default use_std Cargo feature; minimum supported Rust version 1.20, reflecting its role as a foundational, broadly-compatible building-block crate. Code Quality — the crate is small and stable (108 total commits since inception, last major change in 2023), documented via doc-comments and a readme.rs example, with the Drop-based design giving strong compile-time guarantees that guards always run rather than relying on tests to catch missed cleanup; there is no dedicated tests/ directory, relying instead on doctests embedded in lib.rs. API Design — the API surface is intentionally tiny (one function, three macros), making adoption nearly zero-cost: defer! { ... } reads almost like Go’s defer keyword, and guard(value, |v| ...) mirrors closures developers already know from Drop-adjacent patterns, so there’s essentially no learning curve beyond understanding Rust’s panic/unwind model.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search