# What unsoundness can be caused by destructor without PhantomData?

**URL:** <https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219>\
**Category:** help\
**Created:** [October 4, 2022, 6:59am UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219 "2022-10-04T06:59:23Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![zylthinking1](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/zylthinking1/32/21414_2.png) [@zylthinking1](https://users.rust-lang.org/u/zylthinking1)\
**Post date:** [October 4, 2022, 6:59am UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/1 "2022-10-04T06:59:23Z")

</div>

The old Rustonomicon says:

> Another important example is Vec, which is (approximately) defined as follows:
> 
> ```rust
> struct Vec<T> {
> data: *const T, // *const for variance!
> len: usize,
> cap: usize,
> }
> 
> ```
> 
> Unlike the previous example, it appears that everything is exactly as we want. Every generic argument to Vec shows up in at least one field. Good to go!
> 
> Nope.
> 
> The drop checker will generously determine that Vec does not own any values of type T. This will in turn make it conclude that it doesn't need to worry about Vec dropping any T's in its destructor for determining drop check soundness. This will in turn allow people to create \> unsoundness using Vec's destructor.
> 
> In order to tell the drop checker that we do own values of type T, and therefore may drop some T's when we drop, we must add an extra PhantomData saying exactly that:
> 
> ```rust
> use std::marker;
> 
> struct Vec<T> {
> data: *const T, // *const for variance!
> len: usize,
> cap: usize,
> _owns_T: marker::PhantomData<T>,
> }
> 
> ```

While, what is the unsoundness caused because of the absence of PhantomData?

I have seen the document also says:

> But ever since RFC 1238, this is no longer true nor necessary.

But the core question remains... Anyway, data is \*const T, nothing can be done outside of unsafe block, if someone does change data in an unsafe block, seems PhantomData can do nothing to prevent it from being compiled.

---

<div class="post-metadata">

**Author:** ![jbe](https://avatars.discourse-cdn.com/v4/letter/j/f6c823/32.png) [@jbe](https://users.rust-lang.org/u/jbe)\
**Post date:** [October 4, 2022, 7:31am UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/2 "2022-10-04T07:31:50Z")

</div>

I think in past, the [drop check](https://doc.rust-lang.org/nomicon/dropck.html) was only done when you "owned" ` T` (which you can declare with `PhantomData<T>`). This is also what the Nomicon still says in the [Table of `PhantomData` patterns](https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns).

But AFAIK, now this holds generally, as explained on the Drop Check page in the Nomicon:

> **For a generic type to soundly implement drop, its generics arguments must strictly outlive it.**

So it's no longer needed, I guess? But not sure if I'm correct.

---

<div class="post-metadata">

**Author:** ![quinedot](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/quinedot/32/17693_2.png) [@quinedot](https://users.rust-lang.org/u/quinedot)\
**Post date:** [October 4, 2022, 10:11am UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/3 "2022-10-04T10:11:33Z")

</div>

[You can read this prior thread.](https://users.rust-lang.org/t/where-did-unique-t-go/68807/)

In summary:

- It used to work in the dangerous way
- It hasn't since RFC 1238 in most cases, but
  - It's still true if you use the unstable `#[may_dangle]` (RFC 1327)
  - And probably it will stay that way, but
  - The RFCs left it open to revisit and that documentation update is rather new...
    - ...and the nomicon is explicitly non-normative, and the change was accepted with zero input (much less an FCP) from the Rust teams, so 🤷‍♂️

Although unnecessary _today_, it doesn't hurt, so I still say throw it in your struct if the old wording applies to you.

(But what I _really_ want is an official statement on the matter confirming the updated Nomicon. And what I _really **really** _ want is for Rust to have a specification.)

* * *

So what's the unsafe part? Before the change, a destructor of a type with a generic type parameter was allowed to run after the type was invalid (i.e. when the generic type held a lifetime, the destructor could run after the lifetime "expired"). There were guard-rails: If the `Drop` implementation had a trait bound on the generic parameter, and the trait bound exposed any method, the loosening of the rules was not allowed (the outer type had to outlive it's lifetime-carrying type parameter; the outer type was considered to own some instance of the type parameter; the drop had to run before the lifetime became invalid).

Unfortunately, [the guard-rails were not enough.](https://github.com/rust-lang/rust/issues/26656) They are also not sufficient in the face of specialization, should that ever stabilize. So currently, the presence of the type parameter signals ownership... unless you use `#[may_dangle]`.

It's still important in that case as `#[may_dangle]` doesn't even have the not-fully-effective guard-rails.

And now the only way you can drop after your lifetimes expire is if you use `#[may_dangle]` to signal that you promise not to look at what you're dropping. And if what you're dropping doesn't have drops of it's own, that's great! But if it does, you need the `PhantomData` to signal that you "own" some of the generic parameter -- when you drop, some of the parameter will be dropped too. This allows `dropck` to correctly determine when it's sound for your type to drop or not.

[A full example that was linked to in the other thread.](https://users.rust-lang.org/t/phantomdata-and-dropck-confusion/26624/2)

---

<div class="post-metadata">

**Author:** ![Yandros](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/yandros/32/8136_2.png) [@Yandros](https://users.rust-lang.org/u/Yandros)\
**Post date:** [October 4, 2022, 11:16am UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/4 "2022-10-04T11:16:45Z")

</div>

@zylthinking1 doesn't the current documentation of `PhantomData` in the nomicon answer your question? Which part wasn't clear?

This used to be a recurring question given the out-of-date information in the nomicon, as @quinedot's curated list of threads and explanations illustrates, but I'd think that nowadays it shouldn't be the case anymore.

Indeed, [the new documentation says](https://doc.rust-lang.org/1.63.0/nomicon/phantom-data.html#generic-parameters-and-drop-checking) (emphasis added):

> [@https://doc.rust-lang.org/1.63.0/nomicon/phantom-data.html#generic-parameters-and-drop-checking](#):
>
> ## [Generic parameters and drop-checking](https://doc.rust-lang.org/1.63.0/nomicon/phantom-data.html#generic-parameters-and-drop-checking)
> 
> In the past, there used to be another thing to take into consideration.
> 
> This very documentation used to say:
> 
> > **\<snip\>**
> > 
> > Unlike the previous example, it _appears_ that everything is exactly as we want. Every generic argument to Vec shows up in at least one field. Good to go!
> > 
> > Nope.
> > 
> > The drop checker will generously determine that `Vec<T>` does not own any values of type T. This will in turn make it conclude that it doesn't need to worry about Vec dropping any T's in its destructor for determining drop check soundness.
> > 
> > **\<snip\>**
> 
> But ever since [RFC 1238](https://rust-lang.github.io/rfcs/1238-nonparametric-dropck.html), **this is no longer true nor necessary**.
> 
> If you were to write:
> 
> ```rust
> struct Vec<T> {
> data: *const T, // `*const` for variance!
> len: usize,
> cap: usize,
> }
> 
> impl<T> Drop for Vec<T> { /* … */ }
> 
> ```
> 
> then the existence of that `impl<T> Drop for Vec<T>` makes it so Rust will consider that that `Vec<T>` _owns_ values of type `T` (more precisely: may use values of type `T` in its `Drop` implementation), and Rust will thus not allow them to _dangle_ should a `Vec<T>` be dropped.
> 
> **Adding an extra `_owns_T: PhantomData<T>` field is thus _superfluous_ and accomplishes nothing**.
> 
> * * *
> 
> But this situation can sometimes lead to overly restrictive code. That's why the standard library uses an unstable and `unsafe` attribute to opt back into the old "unchecked" drop-checking behavior, that this very documentation warned about: the `#[may_dangle]` attribute.
> 
> ### [An exception: the special case of the standard library and its unstable `#[may_dangle]`](https://doc.rust-lang.org/1.63.0/nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle)
> 
> This section can be skipped if you are only writing your own library code; but if you are curious about what the standard library does with the actual `Vec` definition, you'll notice that it still needs to use a `_owns_T: PhantomData<T>` field for soundness.
> 
> > **Click here to see why**
> >
> > Consider the following example:
> > 
> > ```rust
> > fn main() {
> > let mut v: Vec<&str> = Vec::new();
> > let s: String = "Short-lived".into();
> > v.push(&s);
> > drop(s);
> > } // <- `v` is dropped here
> > 
> > ```
> > 
> > with a classical `impl<T> Drop for Vec<T> {` definition, the above [is denied](https://rust.godbolt.org/z/ans15Kqz3).
> > 
> > Indeed, in this case we have a `Vec</* T = */ &'s str>` vector of `'s`-lived references to `str`ings, but in the case of `let s: String`, it is dropped before the `Vec` is, and thus `'s` **is expired** by the time the `Vec` is dropped, and the `impl<'s> Drop for Vec<&'s str> {` is used.
> > 
> > This means that if such `Drop` were to be used, it would be dealing with an _expired_, or _dangling_ lifetime `'s`. But this is contrary to Rust principles, where **by default all Rust references involved in a function signature are non-dangling and valid to dereference.**
> > 
> > **Hence why Rust has to conservatively deny this snippet.**
> > 
> > And yet, in the case of the real `Vec`, the `Drop` impl does not care about `&'s str`, _since it has no drop glue of its own_: it only wants to deallocate the backing buffer.
> > 
> > In other words, it would be nice if the above snippet was somehow accepted, by special casing `Vec`, or by relying on some special property of `Vec`: `Vec` could try to _promise not to use the `&'s str`s it holds when being dropped_.
> > 
> > This is the kind of `unsafe` promise that can be expressed with `#[may_dangle]`:
> > 
> > ```rust
> > unsafe impl<#[may_dangle] 's> Drop for Vec<&'s str> { /* … */ }
> > 
> > ```
> > 
> > or, more generally:
> > 
> > ```rust
> > unsafe impl<#[may_dangle] T> Drop for Vec<T> { /* … */ }
> > 
> > ```
> > 
> > is the `unsafe` way to opt out of this conservative assumption that Rust's drop checker makes about type parameters of a dropped instance not being allowed to dangle.
> > 
> > And when this is done, such as in the standard library, we need to be careful in the case where `T` has drop glue of its own. In this instance, imagine replacing the `&'s str`s with a `struct PrintOnDrop<'s> /* = */ (&'s str);` which would have a `Drop` impl wherein the inner `&'s str` would be dereferenced and printed to the screen.
> > 
> > Indeed, `Drop for Vec<T> {`, before deallocating the backing buffer, does have to transitively drop each `T` item when it has drop glue; in the case of `PrintOnDrop<'s>`, it means that `Drop for Vec<PrintOnDrop<'s>>` has to transitively drop the `PrintOnDrop<'s>`s elements before deallocating the backing buffer.
> > 
> > So when we said that `'s` `#[may_dangle]`, it was an excessively loose statement. We'd rather want to say: "`'s` may dangle provided it not be involved in some transitive drop glue". Or, more generally, "`T` may dangle provided it not be involved in some transitive drop glue". This "exception to the exception" is a pervasive situation whenever **we own a `T`**. That's why Rust's `#[may_dangle]` is smart enough to know of this opt-out, and will thus be disabled _when the generic parameter is held in an owned fashion_ by the fields of the struct.
> > 
> > Hence why the standard library ends up with:
> > 
> > ```rust
> > // we pinky-swear not to use `T` when dropping a `Vec`…
> > unsafe impl<#[may_dangle] T> Drop for Vec<T> {
> > fn drop(&mut self) {
> > unsafe {
> > if mem::needs_drop::<T>() {
> > /* … except here, that is, … */
> > ptr::drop_in_place::<[T]>(/* … */);
> > }
> > // …
> > dealloc(/* … */)
> > // …
> > }
> > }
> > }
> > 
> > struct Vec<T> {
> > // … except for the fact that a `Vec` owns `T` items and
> > // may thus be dropping `T` items on drop!
> > _owns_T: core::marker::PhantomData<T>,
> > 
> > ptr: *const T, // `*const` for variance (but this does not express ownership of a `T` *per se*)
> > len: usize,
> > cap: usize,
> > }
> > 
> > ```

I updated said docs precisely to clarify these things, so if something isn't clear then further improvements may be needed 🙂

---

<div class="post-metadata">

**Author:** ![zylthinking1](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/zylthinking1/32/21414_2.png) [@zylthinking1](https://users.rust-lang.org/u/zylthinking1)\
**Post date:** [October 4, 2022, 3:46pm UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/5 "2022-10-04T15:46:36Z")

</div>

Sorry, It is my fault. I printed the book into PDF and read it in an eink device.  
Turns out the

> [@https://doc.rust-lang.org/1.63.0/nomicon/phantom-data.html#generic-parameters-and-drop-checking](#):
>
> Click here to see why

part didn't not expand in the PDF, only `Click here to see why` showed, which I didn't notice something related to was absent neither.

The

```rust
fn main() {
    let mut v: Vec<&str> = Vec::new();
    let s: String = "Short-lived".into();
    v.push(&s);
    drop(s);
} 

```

is just the exact example I want to find, showing how the unsoundness occurs.

I didn't realize the T in Vec could be some reference, so confused that Vec owns T, so T will always alive in any touchable code of Vec, including in drop.

---

<div class="post-metadata">

**Author:** ![zylthinking1](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/zylthinking1/32/21414_2.png) [@zylthinking1](https://users.rust-lang.org/u/zylthinking1)\
**Post date:** [October 4, 2022, 4:18pm UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/6 "2022-10-04T16:18:18Z")

</div>

> [@https://doc.rust-lang.org/1.63.0/nomicon/phantom-data.html#generic-parameters-and-drop-checking](#):
>
> The drop checker will generously determine that `Vec<T>` does not own any values of type T. This will in turn make it conclude that it doesn't need to worry about Vec dropping any T's in its destructor for determining drop check soundness.

The old text confuses me a bit.

I can understand why compiler determine that `Vec<T>` does not own any values of type T Without PhantomData; but why make it `conclude that it doesn't need to worry about Vec dropping any T's in its destructor`?

- if T is primary type such as i32, pointer...etc, no dropping T is needed; the dropping thing is about the type of T, not about the PhantomData.

- Vec holds some pointer, which can be invalid freely. So, the compiler surely should worry about the de-referencing thing at any tme, not only in Vec::drop.

Currently in my understanding, It seems to say Vec can't determine the safety of de-referencing the pointer. So, a rule is made out, saying that:

- if a PhantomData exists, then take it as a flag of dangerous, disallow any code potentially harmful to be compiled;

- without PhantomData, take it as safe, compiler will allow code like

passes compilation, if it can't be dereferenced in fact, an UB occurs.

Because the book only says it does not need PhantomData field explicitly today, so the explanation why PhantomData is needed in the old text is not out of date.

I do want to know whether my current understand is right or not.

---

<div class="post-metadata">

**Author:** ![Yandros](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/yandros/32/8136_2.png) [@Yandros](https://users.rust-lang.org/u/Yandros)\
**Post date:** [October 4, 2022, 10:58pm UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/7 "2022-10-04T22:58:59Z")

</div>

> [@zylthinking1](#):
>
> part didn't not expand in the PDF, only `Click here to see why` showed, which I didn't notice something related to was absent neither.

yeah, the `<details>` section has this accessibility problem 🤔

> [@zylthinking1](#):
>
> Sorry, It is my fault.

No, it's easy to dismiss accessibility problems as one's own "oversight" but I think this is a genuine problem of the documentation; I'll thus try to change that `<details>` when I have the time

---

<div class="post-metadata">

**Author:** ![zylthinking1](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/zylthinking1/32/21414_2.png) [@zylthinking1](https://users.rust-lang.org/u/zylthinking1)\
**Post date:** [October 5, 2022, 5:00am UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/8 "2022-10-05T05:00:48Z")

</div>

Maybe the document should not focus on drop, which gives me the impression that PhantomData is strongly related to drop, which in fact is not.

Like the following code, failing to compile while no drop has been implemented for vvec

```rust
use std::marker;

struct vvec<T> {
    data: *const T, // *const for variance!
    len: usize,
    _owns_T: marker::PhantomData<T>,
}

impl<T> vvec<T> {
    fn new() -> Self {
        vvec {
            data: 0 as *const T,
            len: 1,
            _owns_T: PhantomData::<T>,
        }
    }

    fn push(&mut self, x: T) {}
    
    fn hello(&self) {}
}

fn main() {
    let mut v: vvec<&str> = vvec::new();
    {
        {
            let s: String = "Short-lived".into();
            v.push(&s);
        }
        v.hello();
    }
}

```

---

<div class="post-metadata">

**Author:** ![zylthinking1](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/zylthinking1/32/21414_2.png) [@zylthinking1](https://users.rust-lang.org/u/zylthinking1)\
**Post date:** [October 5, 2022, 5:06am UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/9 "2022-10-05T05:06:09Z")

</div>

Wait... code without \_owns\_T fails to compiled neither, then what is the effect of PhantomData?

```rust
use std::marker;

struct vvec<T> {
    data: *const T, // *const for variance!
    len: usize,
    //_owns_T: marker::PhantomData<T>,
}

impl<T> vvec<T> {
    fn new() -> Self {
        vvec {
            data: 0 as *const T,
            len: 1,
           // _owns_T: PhantomData::<T>,
        }
    }

    fn push(&mut self, x: T) {}
    
    fn hello(&self) {}
}

fn main() {
    let mut v: vvec<&str> = vvec::new();
    {
        {
            let s: String = "Short-lived".into();
            v.push(&s);
        }
        v.hello();
    }
}

```

---

<div class="post-metadata">

**Author:** ![quinedot](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/quinedot/32/17693_2.png) [@quinedot](https://users.rust-lang.org/u/quinedot)\
**Post date:** [October 5, 2022, 6:07am UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/10 "2022-10-05T06:07:56Z")

</div>

Depending on how you interpret things, you're either

- creating a `vvec<&'long>` (due to the `.hello()`) and trying to borrow the `'short`-lived `s` for `'long`, or
- creating a `vvec<&'short str>` (due to pushing `&'short s`) and then trying to use it for `'long`.

Either way it's a borrow check borrow violation.

The borrow check considerations under discussion are for `Drop::drop` specifically. Normal uses aren't effected. Moreover, without a `Drop` implementation, you have no `#[may_dangle]`, so you get owning semantics today.

---

<div class="post-metadata">

**Author:** ![zylthinking1](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/zylthinking1/32/21414_2.png) [@zylthinking1](https://users.rust-lang.org/u/zylthinking1)\
**Post date:** [October 5, 2022, 7:18am UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/11 "2022-10-05T07:18:41Z")

</div>

Ok, I would like to rollback to some old rust edition to make the following code compiled, wrongly, which must use PhantomData to fail the compilation.

```rust
use std::marker;

struct vvec<T> {
    data: *const T, // *const for variance!
    len: usize,
    // _owns_t: marker::PhantomData<T>,
}

impl<T> vvec<T> {
    fn new() -> Self {
        vvec {
            data: 0 as *const T,
            len: 1,
            // _owns_t: marker::PhantomData::<T>,
        }
    }

    fn push(&mut self, _x: T) {}
}

impl<T> Drop for vvec<T> {
    fn drop(&mut self) {}
}

fn main() {
    let mut v: vvec<&str> = vvec::new();
    {
        {
            let s: String = "Short-lived".into();
            v.push(&s);
        }
    }
}

```

I have tried 1.48, 1.40. Both refuse to compile.

According to the document:

> Another important example is Vec, which is (approximately) defined as follows:
> 
> ```rust
> struct Vec<T> {
> data: *const T, // *const for variance!
> len: usize,
> cap: usize,
> }
> 
> ```
> 
> Unlike the previous example, it appears that everything is exactly as we want. Every generic argument to Vec shows up in at least one field. Good to go!
> 
> Nope.
> 
> The drop checker will generously determine that Vec does not own any values of type T. This will in turn make it conclude that it doesn't need to worry about Vec dropping any T's in its destructor for determining drop check soundness. This will in turn allow people to create \> unsoundness using Vec's destructor.
> 
> In order to tell the drop checker that we do own values of type T, and therefore may drop some T's when we drop, we must add an extra PhantomData saying exactly that:
> 
> ```rust
> use std::marker;
> 
> struct Vec<T> {
> data: *const T, // *const for variance!
> len: usize,
> cap: usize,
> _owns_T: marker::PhantomData<T>,
> }
> 
> ```

There should be a version that compiler will pass the compilation, but I can't find such a version. 1.40 is a very old version, which I am sure the new behavior of  
`But ever since RFC 1238, this is no longer true nor necessary.` did not apply yet.

Or, There is some misunderstanding, maybe

```rust
fn main() {
    let mut v: vvec<&str> = vvec::new();
    {
        {
            let s: String = "Short-lived".into();
            v.push(&s);
        }
    }
}

```

is not the correct example to show how unsoundness occurs without PhantomData

---

<div class="post-metadata">

**Author:** ![quinedot](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/quinedot/32/17693_2.png) [@quinedot](https://users.rust-lang.org/u/quinedot)\
**Post date:** [October 5, 2022, 4:06pm UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/12 "2022-10-05T16:06:37Z")

</div>

RFC 1238 is older.

[Here's a case, I believe.](https://rust.godbolt.org/z/1f3cPe8f7) Inspired by [#29106.](https://github.com/rust-lang/rust/issues/29106) Uncomment the `PhantomData` or move up a Rust version and compilation fails.

---

<div class="post-metadata">

**Author:** ![zylthinking1](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/zylthinking1/32/21414_2.png) [@zylthinking1](https://users.rust-lang.org/u/zylthinking1)\
**Post date:** [October 6, 2022, 4:21am UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/13 "2022-10-06T04:21:34Z")

</div>

Yes, that is what I am looking for.  
I didn't realize the behavior had changed since version 1.5.0. After all, I read the explanation about PhantomData in the age of rust 2018.

It took me more than 2 years to find the final example; Thank you

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [January 4, 2023, 4:22am UTC](https://users.rust-lang.org/t/what-unsoundness-can-be-caused-by-destructor-without-phantomdata/82219/14 "2023-01-04T04:22:32Z")

</div>

Closed on January 4, 2023, 4:22am UTC

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.
