Skip to content

Behavior of panicking Drop::drop is not properly documented #60611

@gnzlbg

Description

@gnzlbg
Contributor

It was decided in, I think, #14875, that Drop::drop can panic, and if this happens, the value must be leaked (at least in a generic context), that is, it cannot be re-dropped again and doing that could invoke UB (that's at least what generic unsafe code needs to assume).

This does not appear to be documented anywhere. These semantics make the following snippet have undefined behavior due to double-drops (playground uses T = Vec<HasDrop>):

let mut a: T;
let a_raw = &mut a as *mut  T;

match std::panic::catch_unwind(|| {
    // Drop `a` in place:
    unsafe { std::ptr::drop_in_place(a_raw) };
}) {
    // For exposition only, if the value isn't leaked,
    // it will be re-dropped, but one could also try to 
    // explicitly re-drop on drop failure.
    // UB: this will double-drop some previously dropped fields of a
    Err(_) => std::mem::drop(a),
    // If dropping succeeds, leak a
    Ok(()) => std::mem::forget(a),
}

To avoid UB, that snippet must be changed to unconditionally leak the value independently of whether drop_in_place succeeded or failed:

let mut a: T;
let a_raw = &mut *a as *mut T;

std::panic::catch_unwind(|| {
    // Drop `a` in place:
    unsafe { std::ptr::drop_in_place(a_raw) };
});
// Always leak `a`: if dropping failed, some elements will be leaked,
// but there is no way to properly drop them and trying to re-drop
// a could invoke UB
 std::mem::forget(a);

cc @Centril - this might be a T-lang issue, I don't know the best way to word this, and I can't find any RFC designing this part of the language.

Activity

tesuji

tesuji commented on May 7, 2019

@tesuji
Contributor

@rustbot modify labels: T-lang T-doc

added
A-docsArea: Documentation for any part of the project, including the compiler, standard library, and tools
T-langRelevant to the language team
on May 7, 2019
added
A-destructorsArea: Destructors (`Drop`, …)
C-enhancementCategory: An issue proposing an enhancement or a PR with one.
on May 7, 2019
Centril

Centril commented on May 7, 2019

@Centril
Contributor

cc @rust-lang/wg-unsafe-code-guidelines @rust-lang/lang

frewsxcv

frewsxcv commented on May 8, 2019

@frewsxcv
Member

Previous issue: #50765

And also: rust-lang/reference#348

tmandry

tmandry commented on May 16, 2019

@tmandry
Member

Related: #60840 (comment)

The assumption this PR is making is that once [MIR] drop returns to a function, whether it succeeds or panics, it is UB for the function to then access that local.

hkBst

hkBst commented on Mar 14, 2025

@hkBst
Member

https://doc.rust-lang.org/nightly/std/ops/trait.Drop.html#tymethod.drop currently includes
"""
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.
"""

This was added in ##67559

So I think this can be closed.

RalfJung

RalfJung commented on Mar 16, 2025

@RalfJung
Member

Agreed, thanks for gathering the references.

There are some discussions for further changes here, but those are already tracked elsewhere:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-destructorsArea: Destructors (`Drop`, …)A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsC-enhancementCategory: An issue proposing an enhancement or a PR with one.I-needs-decisionIssue: In need of a decision.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @RalfJung@frewsxcv@Centril@gnzlbg@jonas-schievink

        Issue actions

          Behavior of panicking Drop::drop is not properly documented · Issue #60611 · rust-lang/rust