- Feature Name:
drop_types_in_const - Start Date: 2016-01-01
- RFC PR: rust-lang/rfcs#1440
- Rust Issue: rust-lang/rust#33156
Summary
Allow types with destructors to be used in static items, const items, and const functions.
Motivation
Some of the collection types do not allocate any memory when constructed empty (most notably Vec). With the change to make leaking safe, the restriction on static or const items with destructors
is no longer required to be a hard error (as it is safe and accepted that these destructors may never run).
Allowing types with destructors to be directly used in const functions and stored in statics or consts will remove the need to have
runtime-initialization for global variables.
Detailed design
- Lift the restriction on types with destructors being used in
staticorconstitems.statics containing Drop-types will not run the destructor upon program/thread exit.consts containing Drop-types will run the destructor at the appropriate point in the program.- (Optionally adding a lint that warn about the possibility of resource leak)
- Allow instantiating structures with destructors in constant expressions.
- Allow
const fnto return types with destructors. - Disallow constant expressions that require destructors to run during compile-time constant evaluation (i.e: a
drop(foo)in aconst fn).
Examples
Assuming that RwLock and Vec have const fn new methods, the following example is possible and avoids runtime validity checks.
/// Logging output handler
trait LogHandler: Send + Sync {
// ...
}
/// List of registered logging handlers
static S_LOGGERS: RwLock<Vec< Box<LogHandler> >> = RwLock::new( Vec::new() );
/// Just an empty byte vector.
const EMPTY_BYTE_VEC: Vec<u8> = Vec::new();
Disallowed code
static VAL: usize = (Vec::<u8>::new(), 0).1; // The `Vec` would be dropped
const fn sample(_v: Vec<u8>) -> usize {
0 // Discards the input vector, dropping it
}
Drawbacks
Destructors do not run on static items (by design), so this can lead to unexpected behavior when a type's destructor has effects outside the program (e.g. a RAII temporary folder handle, which deletes the folder on drop). However, this can already happen using the lazy_static crate.
A const item's destructor will run at each point where the const item is used. If a const item is never used, its destructor will never run. These behaviors may be unexpected.
Alternatives
- Runtime initialization of a raw pointer can be used instead (as the
lazy_staticcrate currently does on stable). - On nightly, a bug related to
staticandUnsafeCell<Option<T>>can be used to remove the dynamic allocation.- Both of these alternatives require runtime initialization, and incur a checking overhead on subsequent accesses.
- Leaking of objects could be addressed by using C++-style
.dtorssupport- This is undesirable, as it introduces confusion around destructor execution order.
Unresolved questions
- TBD