Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/destructors.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,10 +345,14 @@ let x = (&temp()).use_temp(); // ERROR

## Not running destructors

Not running destructors in Rust is safe even if it has a type that isn't
`'static`. [`std::mem::ManuallyDrop`] provides a wrapper to prevent a
[`std::mem::forget`] can be used to prevent the destructor of a variable from being run,
and [`std::mem::ManuallyDrop`] provides a wrapper to prevent a
variable or field from being dropped automatically.

> Note: Preventing a destructor from being run via `forget` or other means is safe in Rust
> even if it has a type that isn't `'static`. This means that publicly exposed APIs cannot
> rely on destructor being run for soundness.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like it might be good to expand a little on this: for one thing, publicly exposed APIs seems like a somewhat "interesting" term. Certainly even in a crate-local context I would expect to see unsafe fn on the constructor or similar if the destructor must run for soundness reasons.

Maybe we can adjust to something like?

Note that while code can safely prevent a destructor from running, they are still guaranteed to automatically run in places defined by this document (such as the end of scopes). Authors may rely on destructors running at these locations for soundness, but must not otherwise assume destructors are run.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping @nbdd0121, was wondering if you'd be willing to change the note to something like the suggestion given here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for not being responsive, I am quite busy recently.

I don't think it's good to explicit saying that "you can expect destructor at the end of scope to run for soundness", as I think it could create additional confusion, as these are really just part of control flow that users expect.

The purpose of this change is to keep its original intention while removing the possibility to interpret it as a permit for compilers to omit destructor calls.

Copy link
Contributor

@ehuss ehuss Mar 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, I was just checking in.

How about something like this?

Note: Preventing a destructor from being run via std::mem::forget or other
means is safe even if it has a type that isn't 'static.
Besides the places where destructors are guaranteed to run as defined by
this document, types may not safely rely on a destructor being run for
soundness.

I'm trying to blend the different ideas here:

  • It should always be safe to call forget.
  • There are places where destructors are guaranteed to run, and you may rely on that.
  • Types may not rely on their destructor being run for soundness.

I agree with Mark about the "publicly exposed APIs", so I'm trying to avoid that phrasing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds very good. I have applied your suggestion.


[Assignment]: expressions/operator-expr.md#assignment-expressions
[binding modes]: patterns.md#binding-modes
[closure]: types/closure.md
Expand Down Expand Up @@ -395,4 +399,5 @@ variable or field from being dropped automatically.

[`<T as std::ops::Drop>::drop`]: ../std/ops/trait.Drop.html#tymethod.drop
[`std::ptr::drop_in_place`]: ../std/ptr/fn.drop_in_place.html
[`std::mem::forget`]: ../std/mem/fn.forget.html
[`std::mem::ManuallyDrop`]: ../std/mem/struct.ManuallyDrop.html