Skip to content

Commit

Permalink
EntryWriter: Add comments for why ManuallyDrop is OK
Browse files Browse the repository at this point in the history
This wasn't immediately obvious to me at least.
xref: #376 (comment)

Signed-off-by: Colin Walters <[email protected]>
  • Loading branch information
cgwalters committed Sep 26, 2024
1 parent b8b5ea7 commit cabe09e
Showing 1 changed file with 11 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,8 @@ impl<T: Write + Seek> SeekWrite for T {
/// After writing all data to the entry, it must be finalized either by
/// explicitly calling [`EntryWriter::finish`] or by letting it drop.
pub struct EntryWriter<'a> {
// NOTE: Do not add any fields here which require Drop!
// See the comment below in do_finish().
obj: &'a mut dyn SeekWrite,
header: &'a mut Header,
written: u64,
Expand All @@ -527,6 +529,15 @@ impl EntryWriter<'_> {

/// Finish writing the current entry in the archive.
pub fn finish(self) -> io::Result<()> {
// NOTE: This is an optimization for "fallible destructuring".
// we want finish() to return an error, but we also need to invoke
// cleanup in our Drop handler, which will run unconditionally
// and try to do the same work.
// By using ManuallyDrop, we suppress that drop. However, this would
// be a memory leak if we ever had any struct members which required
// Drop - which we don't right now.
// But if we ever gain one, we will need to change to use e.g. Option<>
// around some of the fields or have a `bool finished` etc.
let mut this = std::mem::ManuallyDrop::new(self);
this.do_finish()
}
Expand Down

0 comments on commit cabe09e

Please sign in to comment.