Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
bitcoinleveldb-util
Utility components used by the bitcoin-rs / bitcoinleveldb codebase, focused on precise control over object lifetime and destructor behavior.
This crate is intentionally small and low-level. It exports primitives that help emulate C++-style "never call the destructor" patterns in Rust, primarily for function-local statics and other long-lived objects that must not run cleanup code on shutdown.
Overview
The key types provided are:
DoNotDestruct– A test/utility struct whose destructor must never run. If itsDropimplementation is invoked, the process will immediately abort.NoDestructor<T>– A wrapper that stores a fully-initialized instance ofTinsideMaybeUninit<T>and never drops it. This is particularly useful for singletons, function-local statics, or global state that must remain valid for the lifetime of the process and does not require orderly teardown.NoDestructorTest– A trivial grouping struct, mainly used for tests.
The semantics are deliberately strict and closer to systems-programming idioms, trading graceful shutdown for predictable performance and the avoidance of complex destructor interactions at process exit.
DoNotDestruct
use DoNotDestruct;
// Panics? No. If this is dropped, the process aborts.
let obj = new;
// Read and write fields via generated getters/setters (from `getset`):
let a = *obj.a;
let b = *obj.b;
obj.set_a;
obj.set_b;
Behavior
- Any attempt to drop a
DoNotDestructinstance (including unwinding across stack frames) will unconditionally callprocess::abort(). - The type is primarily intended as a guardrail in tests or as documentation of intent: this object is meant to be effectively immortal.
Construction
Logging macros (info!, error!) are used from the standard Rust logging ecosystem (e.g., log crate + chosen logger backend). To see log output, configure a logger in your binary (e.g. env_logger, tracing_subscriber, etc.).
NoDestructor<T>
NoDestructor<T> stores an instance of T in MaybeUninit<T>, ensuring that Rust never runs its destructor. This is the Rust analogue of C++ code that uses aligned storage plus placement-new and deliberately omits destructor calls.
Type definition
use MaybeUninit;
Constructor
Usage:
use NoDestructor;
Pointer access
Important properties:
- The destructor of
InstanceTypeis never called. get()returns a*mut InstanceTypeeven though&selfis shared; this mirrors some C++ patterns but deviates from idiomatic Rust. The burden of ensuring sound aliasing rules and exclusive mutation lies with the caller.- The underlying
InstanceTypemust be fully initialized by the time you callget()(which is guaranteed for instances constructed viaNoDestructor::new).
Safety considerations
While NoDestructor<T> itself is safe to construct and use at the type level, it allows patterns where you can trivially violate Rust's higher-level aliasing disciplines if misused. You must:
- Ensure that at most one mutable reference to the underlying
Texists at any time. - Ensure no mutable reference is used concurrently with any shared references where
T's invariants would not permit it. - Accept that resources owned by
T(file descriptors, sockets, memory buffers, lock guards, etc.) will never be released by RAII; they must either be leak-tolerant or managed manually.
This design is appropriate for process-long singletons where resource reclamation is unnecessary or undesirable.
NoDestructorTest
A minimal struct serving as a convenient grouping for tests. Its presence indicates that the crate is used to validate and regression-test the above lifetime primitives.
Design rationale
The patterns implemented in this crate arise from a specific class of problems in systems and database code:
- Some singletons or subsystems are more expensive, brittle, or risky to tear down than to leak.
- During shutdown, destructors may depend on global order-of-destruction guarantees that are fragile or impossible to enforce (especially across FFI boundaries or multiple static initializers).
- In such contexts, an explicit decision is made to construct once and never destruct, trading finite resource leaks at process exit for determinism during the lifetime of the program.
Relation to C++ patterns
C++ often uses patterns like:
static SomeType instance;with non-trivial destructors, whose order-of-destruction across translation units is notoriously complex.std::aligned_storage+ placement-new, followed by intentionally omitting~SomeType()calls.
NoDestructor<T> mirrors the second approach using MaybeUninit<T> in Rust. DoNotDestruct serves as an explicit sentinel type that aborts if any destructor tries to execute, making tests detect any unintentional destruction.
Logging
The snippets use logging macros such as info!, error!, and trace!. At integration time, you will typically:
[]
= "0.4"
# and a backend of your choice, e.g.
= "0.11"
Initialize logging in your binary:
This allows you to observe constructor calls and any unexpected destructor activity during testing.
When not to use this crate
Avoid these primitives if:
- You want idiomatic Rust RAII where destructors reliably run and free resources.
- You require structured teardown, e.g., for graceful shutdown of network servers.
- You can express your requirements using
lazy_static,once_cell, orstd::sync::OnceLockwithout destructors that cause problems.
Use this crate when you:
- Need full control over when (or whether) destructors execute.
- Are porting C++ code that already relies on immortal singletons or non-dropping patterns.
- Operate in a low-level environment (such as an embedded database, block storage engine, or consensus node) where teardown cost and complexity outweigh the benefits.
Repository and license
- Repository: https://github.com/klebs6/bitcoin-rs
- Crate:
bitcoinleveldb-util - License: MIT
This crate is a component in the broader bitcoin-rs ecosystem. Consult that repository for examples of how these primitives are used in practice inside a leveldb-like storage engine and related Bitcoin infrastructure.