pub trait Drop {
// Required method
fn drop(&mut self);
}
Expand description
Custom code within the destructor.
When a value is no longer needed, Rust will run a โdestructorโ on that value. The most common way that a value is no longer needed is when it goes out of scope. Destructors may still run in other circumstances, but weโre going to focus on scope for the examples here. To learn about some of those other cases, please see the reference section on destructors.
This destructor consists of two components:
- A call to
Drop::drop
for that value, if this specialDrop
trait is implemented for its type. - The automatically generated โdrop glueโ which recursively calls the destructors of all the fields of this value.
As Rust automatically calls the destructors of all contained fields,
you donโt have to implement Drop
in most cases. But there are some cases where
it is useful, for example for types which directly manage a resource.
That resource may be memory, it may be a file descriptor, it may be a network socket.
Once a value of that type is no longer going to be used, it should โclean upโ its
resource by freeing the memory or closing the file or socket. This is
the job of a destructor, and therefore the job of Drop::drop
.
ยงExamples
To see destructors in action, letโs take a look at the following program:
struct HasDrop;
impl Drop for HasDrop {
fn drop(&mut self) {
println!("Dropping HasDrop!");
}
}
struct HasTwoDrops {
one: HasDrop,
two: HasDrop,
}
impl Drop for HasTwoDrops {
fn drop(&mut self) {
println!("Dropping HasTwoDrops!");
}
}
fn main() {
let _x = HasTwoDrops { one: HasDrop, two: HasDrop };
println!("Running!");
}
Rust will first call Drop::drop
for _x
and then for both _x.one
and _x.two
,
meaning that running this will print
Running!
Dropping HasTwoDrops!
Dropping HasDrop!
Dropping HasDrop!
Even if we remove the implementation of Drop
for HasTwoDrop
, the destructors of its fields are still called.
This would result in
Running!
Dropping HasDrop!
Dropping HasDrop!
ยงYou cannot call Drop::drop
yourself
Because Drop::drop
is used to clean up a value, it may be dangerous to use this value after
the method has been called. As Drop::drop
does not take ownership of its input,
Rust prevents misuse by not allowing you to call Drop::drop
directly.
In other words, if you tried to explicitly call Drop::drop
in the above example, youโd get a compiler error.
If youโd like to explicitly call the destructor of a value, mem::drop
can be used instead.
ยงDrop order
Which of our two HasDrop
drops first, though? For structs, itโs the same
order that theyโre declared: first one
, then two
. If youโd like to try
this yourself, you can modify HasDrop
above to contain some data, like an
integer, and then use it in the println!
inside of Drop
. This behavior is
guaranteed by the language.
Unlike for structs, local variables are dropped in reverse order:
struct Foo;
impl Drop for Foo {
fn drop(&mut self) {
println!("Dropping Foo!")
}
}
struct Bar;
impl Drop for Bar {
fn drop(&mut self) {
println!("Dropping Bar!")
}
}
fn main() {
let _foo = Foo;
let _bar = Bar;
}
This will print
Dropping Bar!
Dropping Foo!
Please see the reference for the full rules.
ยงCopy
and Drop
are exclusive
You cannot implement both Copy
and Drop
on the same type. Types that
are Copy
get implicitly duplicated by the compiler, making it very
hard to predict when, and how often destructors will be executed. As such,
these types cannot have destructors.
ยงDrop check
Dropping interacts with the borrow checker in subtle ways: when a type T
is being implicitly
dropped as some variable of this type goes out of scope, the borrow checker needs to ensure that
calling T
โs destructor at this moment is safe. In particular, it also needs to be safe to
recursively drop all the fields of T
. For example, it is crucial that code like the following
is being rejected:
use std::cell::Cell;
struct S<'a>(Cell<Option<&'a S<'a>>>, Box<i32>);
impl Drop for S<'_> {
fn drop(&mut self) {
if let Some(r) = self.0.get() {
// Print the contents of the `Box` in `r`.
println!("{}", r.1);
}
}
}
fn main() {
// Set up two `S` that point to each other.
let s1 = S(Cell::new(None), Box::new(42));
let s2 = S(Cell::new(Some(&s1)), Box::new(42));
s1.0.set(Some(&s2));
// Now they both get dropped. But whichever is the 2nd one
// to be dropped will access the `Box` in the first one,
// which is a use-after-free!
}
The Nomicon discusses the need for drop check in more detail.
To reject such code, the โdrop checkโ analysis determines which types and lifetimes need to
still be live when T
gets dropped. The exact details of this analysis are not yet
stably guaranteed and subject to change. Currently, the analysis works as follows:
- If
T
has no drop glue, then trivially nothing is required to be live. This is the case if neitherT
nor any of its (recursive) fields have a destructor (impl Drop
).PhantomData
, arrays of length 0 andManuallyDrop
are considered to never have a destructor, no matter their field type. - If
T
has drop glue, then, for all typesU
that are owned by any field ofT
, recursively add the types and lifetimes that need to be live whenU
gets dropped. The set of owned types is determined by recursively traversingT
:- Recursively descend through
PhantomData
,Box
, tuples, and arrays (excluding arrays of length 0). - Stop at reference and raw pointer types as well as function pointers and function items; they do not own anything.
- Stop at non-composite types (type parameters that remain generic in the current context and
base types such as integers and
bool
); these types are owned. - When hitting an ADT with
impl Drop
, stop there; this type is owned. - When hitting an ADT without
impl Drop
, recursively descend to its fields. (For anenum
, consider all fields of all variants.)
- Recursively descend through
- Furthermore, if
T
implementsDrop
, then all generic (lifetime and type) parameters ofT
must be live.
In the above example, the last clause implies that 'a
must be live when S<'a>
is dropped,
and hence the example is rejected. If we remove the impl Drop
, the liveness requirement
disappears and the example is accepted.
There exists an unstable way for a type to opt-out of the last clause; this is called โdrop
check eyepatchโ or may_dangle
. For more details on this nightly-only feature, see the
discussion in the Nomicon.
Required Methodsยง
1.0.0 ยท Sourcefn drop(&mut self)
fn drop(&mut self)
Executes the destructor for this type.
This method is called implicitly when the value goes out of scope,
and cannot be called explicitly (this is compiler error E0040).
However, the mem::drop
function in the prelude can be
used to call the argumentโs Drop
implementation.
When this method has been called, self
has not yet been deallocated.
That only happens after the method is over.
If this wasnโt the case, self
would be a dangling reference.
ยงPanics
Implementations should generally avoid panic!
ing, because drop()
may itself be called
during unwinding due to a panic, and if the drop()
panics in that situation (a โdouble
panicโ), this will likely abort the program. It is possible to check panicking()
first,
which may be desirable for a Drop
implementation that is reporting a bug of the kind
โyou didnโt finish using this before it was droppedโ; but most types should simply clean up
their owned allocations or other resources and return normally from drop()
, regardless of
what state they are in.
Note that even if this panics, the value is considered to be dropped;
you must not cause drop
to be called again. This is normally automatically
handled by the compiler, but when using unsafe code, can sometimes occur
unintentionally, particularly when using ptr::drop_in_place
.
Implementorsยง
impl Drop for ResetErrorHookOnDrop
impl Drop for SuppressResourceLoad
impl Drop for TaskHandle
impl Drop for BytesMut
impl Drop for Bytes
impl Drop for LocalWaker
impl Drop for Waker
impl Drop for CString
impl Drop for alloc::string::Drain<'_>
impl Drop for OwnedFd
impl Drop for Error
impl Drop for Report
impl Drop for Buf
impl Drop for Config
impl Drop for Cred
impl Drop for DiffStats
impl Drop for Index
impl Drop for Indexer<'_>
impl Drop for Mailmap
impl Drop for MergeFileResult
impl Drop for OidArray
impl Drop for Pathspec
impl Drop for Reflog
impl Drop for Repository
impl Drop for StringArray
impl Drop for git2::transaction::Transaction<'_>
impl Drop for Transport
impl Drop for Worktree
impl Drop for Asn1BitString
impl Drop for Asn1Enumerated
impl Drop for Asn1GeneralizedTime
impl Drop for Asn1Integer
impl Drop for Asn1Object
impl Drop for Asn1OctetString
impl Drop for Asn1String
impl Drop for Asn1Time
impl Drop for BigNum
impl Drop for BigNumContext
impl Drop for Cipher
impl Drop for CipherCtx
impl Drop for CmsContentInfo
impl Drop for Conf
impl Drop for Deriver<'_>
impl Drop for DsaSig
impl Drop for EcGroup
impl Drop for EcPoint
impl Drop for EcdsaSig
impl Drop for Decrypter<'_>
impl Drop for Encrypter<'_>
impl Drop for Hasher
impl Drop for LibCtx
impl Drop for Md
impl Drop for MdCtx
impl Drop for OcspBasicResponse
impl Drop for OcspCertId
impl Drop for OcspOneReq
impl Drop for OcspRequest
impl Drop for OcspResponse
impl Drop for Pkcs7
impl Drop for Pkcs7Signed
impl Drop for Pkcs7SignerInfo
impl Drop for Pkcs12
impl Drop for Provider
impl Drop for Signer<'_>
impl Drop for Verifier<'_>
impl Drop for SrtpProtectionProfile
impl Drop for Ssl
impl Drop for SslContext
impl Drop for SslSession
impl Drop for OpensslString
impl Drop for X509Store
impl Drop for X509StoreBuilder
impl Drop for AccessDescription
impl Drop for DistPoint
impl Drop for DistPointName
impl Drop for GeneralName
impl Drop for X509
impl Drop for X509Algorithm
impl Drop for X509Crl
impl Drop for X509Extension
impl Drop for X509Name
impl Drop for X509NameEntry
impl Drop for X509Object
impl Drop for X509Req
impl Drop for X509Revoked
impl Drop for X509StoreContext
impl Drop for X509VerifyParam
impl Drop for TempDir
impl Drop for TempPath
impl Drop for Taker
impl Drop for JsValue
impl Drop for AbortHandle
impl Drop for AeadKey
impl Drop for AggregationLimitsGuard
impl Drop for AlignedVec
impl Drop for AllocScratch
impl Drop for Ast
A custom Drop
impl is used for Ast
such that it uses constant stack
space but heap space proportional to the depth of the Ast
.
impl Drop for CancellationToken
impl Drop for ClassSet
A custom Drop
impl is used for ClassSet
such that it uses constant
stack space but heap space proportional to the depth of the ClassSet
.
impl Drop for DCtx<'_>
impl Drop for DefaultGuard
impl Drop for DropGuard
impl Drop for DropGuardRef<'_>
impl Drop for DuplexStream
impl Drop for Encoder<'_>
impl Drop for Enter
impl Drop for EnteredSpan
impl Drop for Erased
If into_inner() wasnโt called, the value would leak and destructors wouldnโt run, this prevents that from happening.
impl Drop for ErasedLocal
If into_inner() wasnโt called, the value would leak and destructors wouldnโt run, this prevents that from happening.
impl Drop for EventSource
impl Drop for EventSourceSubscription
impl Drop for FileProvider
impl Drop for GaiFuture
impl Drop for Guard
impl Drop for Hir
A custom Drop
impl is used for HirKind
such that it uses constant stack
space but heap space proportional to the depth of the total Hir
.
impl Drop for HpkePrivateKey
impl Drop for LocalEnterGuard
impl Drop for LocalHandle
impl Drop for LocalRuntime
impl Drop for LocalSet
impl Drop for MeasureTime
impl Drop for Notified<'_>
impl Drop for OkmBlock
impl Drop for OwnedNotified
impl Drop for OwnedSemaphorePermit
impl Drop for OwnedWriteHalf
impl Drop for OwnedWriteHalf
impl Drop for ReadableStreamBYOBReader<'_>
impl Drop for ReadableStreamDefaultReader<'_>
impl Drop for RecvAncillaryBuffer<'_>
impl Drop for RecvStream
impl Drop for RestoreOnPending
impl Drop for Runtime
impl Drop for SelectedOperation<'_>
impl Drop for SemaphoreGuard<'_>
impl Drop for SemaphoreGuardArc
impl Drop for SemaphorePermit<'_>
impl Drop for Span
impl Drop for SpecialNonReactiveZoneGuard
impl Drop for SqliteOwnedBuf
impl Drop for Tag
impl Drop for ThreadPool
impl Drop for ThreadPool
impl Drop for WaitGroup
impl Drop for WebSocket
impl Drop for WritableStreamDefaultWriter<'_>
impl<'a> Drop for OdbObject<'a>
impl<'a> Drop for Signature<'a>
impl<'a> Drop for TreeEntry<'a>
impl<'a> Drop for ParseBuffer<'a>
impl<'a> Drop for PathSegmentsMut<'a>
impl<'a> Drop for UrlQuery<'a>
impl<'a> Drop for CCtx<'a>
impl<'a> Drop for CDict<'a>
impl<'a> Drop for CowArcStr<'a>
impl<'a> Drop for CowRcStr<'a>
impl<'a> Drop for DDict<'a>
impl<'a> Drop for Drain<'a>
impl<'a> Drop for Entered<'a>
impl<'a> Drop for LocalTimerFuture<'a>
impl<'a, I> Drop for itertools::groupbylazy::Chunk<'a, I>
impl<'a, I> Drop for Chunk<'a, I>
impl<'a, K, F, A> Drop for DrainFilter<'a, K, F, A>
impl<'a, K, I, F> Drop for itertools::groupbylazy::Group<'a, K, I, F>
impl<'a, K, I, F> Drop for Group<'a, K, I, F>
impl<'a, K, V> Drop for slotmap::basic::Drain<'a, K, V>where
K: Key,
impl<'a, K, V> Drop for slotmap::dense::Drain<'a, K, V>where
K: Key,
impl<'a, K, V> Drop for slotmap::hop::Drain<'a, K, V>where
K: Key,
impl<'a, K, V> Drop for slotmap::secondary::Drain<'a, K, V>where
K: Key,
impl<'a, K, V> Drop for slotmap::sparse_secondary::Drain<'a, K, V>where
K: Key,
impl<'a, K, V, F, A> Drop for DrainFilter<'a, K, V, F, A>
impl<'a, MutexType> Drop for GenericSemaphoreAcquireFuture<'a, MutexType>where
MutexType: RawMutex,
impl<'a, MutexType> Drop for GenericWaitForEventFuture<'a, MutexType>where
MutexType: RawMutex,
impl<'a, MutexType, T> Drop for ChannelReceiveFuture<'a, MutexType, T>
impl<'a, MutexType, T> Drop for ChannelSendFuture<'a, MutexType, T>
impl<'a, MutexType, T> Drop for GenericMutexLockFuture<'a, MutexType, T>where
MutexType: RawMutex,
impl<'a, MutexType, T> Drop for StateReceiveFuture<'a, MutexType, T>where
T: Clone,
impl<'a, R, G, T> Drop for MappedReentrantMutexGuard<'a, R, G, T>where
R: RawMutex + 'a,
G: GetThreadId + 'a,
T: 'a + ?Sized,
impl<'a, R, G, T> Drop for ReentrantMutexGuard<'a, R, G, T>where
R: RawMutex + 'a,
G: GetThreadId + 'a,
T: 'a + ?Sized,
impl<'a, R, T> Drop for MappedMutexGuard<'a, R, T>where
R: RawMutex + 'a,
T: 'a + ?Sized,
impl<'a, R, T> Drop for MappedRwLockReadGuard<'a, R, T>where
R: RawRwLock + 'a,
T: 'a + ?Sized,
impl<'a, R, T> Drop for MappedRwLockWriteGuard<'a, R, T>where
R: RawRwLock + 'a,
T: 'a + ?Sized,
impl<'a, R, T> Drop for MutexGuard<'a, R, T>where
R: RawMutex + 'a,
T: 'a + ?Sized,
impl<'a, R, T> Drop for RwLockReadGuard<'a, R, T>where
R: RawRwLock + 'a,
T: 'a + ?Sized,
impl<'a, R, T> Drop for RwLockUpgradableReadGuard<'a, R, T>where
R: RawRwLockUpgrade + 'a,
T: 'a + ?Sized,
impl<'a, R, T> Drop for RwLockWriteGuard<'a, R, T>where
R: RawRwLock + 'a,
T: 'a + ?Sized,
impl<'a, T> Drop for flams_router_vscode::server_fn::axum_export::http::header::Drain<'a, T>
impl<'a, T> Drop for ValueDrain<'a, T>
impl<'a, T> Drop for Drain<'a, T>where
T: 'a + Array,
impl<'a, T> Drop for Drain<'a, T>
impl<'a, T> Drop for Drain<'a, T>where
T: Send,
impl<'a, T> Drop for Locked<'a, T>
impl<'a, T> Drop for MappedMutexGuard<'a, T>where
T: ?Sized,
impl<'a, T> Drop for RecvFut<'a, T>
impl<'a, T> Drop for RwLockMappedWriteGuard<'a, T>where
T: ?Sized,
impl<'a, T> Drop for RwLockReadGuard<'a, T>where
T: ?Sized,
impl<'a, T> Drop for RwLockWriteGuard<'a, T>where
T: ?Sized,
impl<'a, T> Drop for SendFut<'a, T>
impl<'a, T> Drop for SpinMutexGuard<'a, T>where
T: ?Sized,
impl<'a, T, A> Drop for DrainSorted<'a, T, A>
impl<'a, T, C> Drop for Ref<'a, T, C>
impl<'a, T, C> Drop for RefMut<'a, T, C>
impl<'a, T, C> Drop for Entry<'a, T, C>where
C: Config,
impl<'a, T, U> Drop for FromColorMutGuard<'a, T, U>
impl<'a, T, U> Drop for FromColorUnclampedMutGuard<'a, T, U>
impl<'a, T, const N: usize> Drop for Drain<'a, T, N>where
T: 'a,
impl<'buffers> Drop for Patch<'buffers>
impl<'c, DB> Drop for Transaction<'c, DB>where
DB: Database,
impl<'cfg> Drop for ConfigEntries<'cfg>
impl<'cfg> Drop for ConfigEntry<'cfg>
impl<'data, T> Drop for AncillaryIter<'data, T>
impl<'data, T> Drop for Drain<'data, T>where
T: Send,
impl<'e, E, W> Drop for EncoderWriter<'e, E, W>where
E: Engine,
W: Write,
impl<'f> Drop for VaListImpl<'f>
impl<'index> Drop for IndexConflicts<'index>
impl<'ps> Drop for PathspecMatchList<'ps>
impl<'q> Drop for QueryLogger<'q>
impl<'reader> Drop for IntoAsyncRead<'reader>
impl<'reader> Drop for IntoStream<'reader>
impl<'repo> Drop for Blame<'repo>
impl<'repo> Drop for Blob<'repo>
impl<'repo> Drop for BlobWriter<'repo>
impl<'repo> Drop for Branches<'repo>
impl<'repo> Drop for Commit<'repo>
impl<'repo> Drop for Describe<'repo>
impl<'repo> Drop for Diff<'repo>
impl<'repo> Drop for AnnotatedCommit<'repo>
impl<'repo> Drop for Note<'repo>
impl<'repo> Drop for Notes<'repo>
impl<'repo> Drop for Object<'repo>
impl<'repo> Drop for Odb<'repo>
impl<'repo> Drop for OdbPackwriter<'repo>
impl<'repo> Drop for OdbReader<'repo>
impl<'repo> Drop for OdbWriter<'repo>
impl<'repo> Drop for PackBuilder<'repo>
impl<'repo> Drop for Rebase<'repo>
impl<'repo> Drop for Reference<'repo>
impl<'repo> Drop for References<'repo>
impl<'repo> Drop for Remote<'repo>
impl<'repo> Drop for Revwalk<'repo>
impl<'repo> Drop for Statuses<'repo>
impl<'repo> Drop for Submodule<'repo>
impl<'repo> Drop for git2::tag::Tag<'repo>
impl<'repo> Drop for Tree<'repo>
impl<'repo> Drop for TreeBuilder<'repo>
impl<'repo, 'connection, 'cb> Drop for RemoteConnection<'repo, 'connection, 'cb>
impl<'rwlock, T> Drop for RwLockReadGuard<'rwlock, T>where
T: ?Sized,
impl<'rwlock, T, R> Drop for RwLockUpgradableGuard<'rwlock, T, R>where
T: ?Sized,
impl<'rwlock, T, R> Drop for RwLockWriteGuard<'rwlock, T, R>where
T: ?Sized,
impl<A> Drop for IntoIter<A>where
A: Array,
impl<A> Drop for SmallVec<A>where
A: Array,
impl<A, B> Drop for ArcUnion<A, B>
impl<C> Drop for CartableOptionPointer<C>where
C: CartablePointerLike,
impl<D> Drop for IndexWriter<D>where
D: Document,
impl<DB> Drop for PoolConnection<DB>where
DB: Database,
Returns the connection to the [Pool
][crate::pool::Pool] it was checked-out from.