# \[Resolved\] PhantomData and Unpin

**URL:** <https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393>\
**Category:** language design\
**Created:** [November 29, 2019, 10:47am UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393 "2019-11-29T10:47:53Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![nlordell](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nlordell/32/6306_2.png) [@nlordell](https://internals.rust-lang.org/u/nlordell)\
**Post date:** [November 29, 2019, 10:47am UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/1 "2019-11-29T10:47:53Z")

</div>

I noticed that `PhantomData` only implements `Unpin` for `T: Unpin` (through auto-trait implementation). Is there a reason for this? Isn't `PhantomData` completely empty and, as such, can always safely implement `Unpin`?

Would it be appropriate to implement:

```rust
impl<T: ?Sized> Unpin for PhantomData<T> {}

```

---

<div class="post-metadata">

**Author:** ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)\
**Post date:** [November 29, 2019, 11:05am UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/2 "2019-11-29T11:05:22Z")

</div>

`PhantomData<T>` is meant to behave the same as `T` at compile time.

---

<div class="post-metadata">

**Author:** ![nlordell](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nlordell/32/6306_2.png) [@nlordell](https://internals.rust-lang.org/u/nlordell)\
**Post date:** [November 29, 2019, 11:28am UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/3 "2019-11-29T11:28:27Z")

</div>

Hm, sorry but I don't think I understand. From reading the std docs the impression that act like a compiler marker that owns some `T` but not necessarily behaves like `T`. Here is an example that I consider to be somewhat similar:

```rust
use std::marker::PhantomData;
fn assert_sized<T: Sized>() {}
fn main() {
    assert_sized::<PhantomData<[u8]>>(); // OK
    assert_sized::<[u8]>(); // Compile error
}

```

**edit** : Just to clarify - here the `PhantomData` is `SIzed` event if `T` is not. To me this is analogous to `PhantomData` being `Unpin` even if `T` is not.

---

<div class="post-metadata">

**Author:** ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)\
**Post date:** [November 29, 2019, 11:50am UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/4 "2019-11-29T11:50:36Z")

</div>

What is the motivation for making PhantomData implement Unpin?

I don't know of a reason why it _can't_, but that's different from arguing that it should. IIUC, making PhantomData impl Unpin would make a lot of PhantomData-using types automatically impl Unpin as well, but I would expect that for most PhantomData-using types it's not at all obvious whether Unpin is right and that needs to be decided on a case-by-case basis.

---

<div class="post-metadata">

**Author:** ![nlordell](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nlordell/32/6306_2.png) [@nlordell](https://internals.rust-lang.org/u/nlordell)\
**Post date:** [November 29, 2019, 1:03pm UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/5 "2019-11-29T13:03:09Z")

</div>

Ah, that'a is a valid point. So a couple things:

- One of the motivations of my question was "is there something super obvious that I'm missing why `PhantomData` can't implement `Unpin` for `T: !Unpin`". From what I'm understanding, while `PhantomData` itself is always safe to be `Unpin` there might be some unsoundness that needs to be explored further if it were always automatically implemented for all `T`.
- To answer your question, I think that the fact that `Unpin` is an auto-trait to me signals that as many things as possible that can safely be `Unpin` should.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [November 29, 2019, 1:07pm UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/6 "2019-11-29T13:07:41Z")

</div>

All auto-traits for `PhantomData` depend on `T`: [https://doc.rust-lang.org/std/marker/struct.PhantomData.html#synthetic-implementations](https://doc.rust-lang.org/std/marker/struct.PhantomData.html#synthetic-implementations)

---

<div class="post-metadata">

**Author:** ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)\
**Post date:** [November 29, 2019, 1:07pm UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/7 "2019-11-29T13:07:44Z")

</div>

`PhantomData<&UnSync>` could implement `Send`, even though `&UnSync` doesnt, but that would make `PhantomData` useless. In fact `PhantomData` is mostly used to prevent implementation of auto traits when the wrapped type doesn't implement it. For example `Box<T>` shouldn't implement `Send` when `T` doesn't. `Box` uses `PhantomData<T>` to do this.

---

<div class="post-metadata">

**Author:** ![nlordell](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nlordell/32/6306_2.png) [@nlordell](https://internals.rust-lang.org/u/nlordell)\
**Post date:** [November 29, 2019, 1:45pm UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/8 "2019-11-29T13:45:24Z")

</div>

OK, I think I understand. `PhantomData<T>` is intended for all intents and purposes to behave exactly like `T` with the exception of size. This means that certain safety related behaviours of `T` (such as `Send`, `Sync`, `Unpin` etc.) must also be maintained. I think in the specific case I was thinking of just using `PhantomData` to use a type's associated functions, which is something that `PhantomData` allows but not necessarily its primary purpose. (Please correct me if I'm wrong).

To that extent, I think what I was looking for in my particular case was to use `PhantomData<Box<T>>` or similar to allow both the ability to use a type's associated functions and also always be `Unpin`.

Thanks for the clarification guys, I really appreciate it.

---

<div class="post-metadata">

**Author:** ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)\
**Post date:** [November 29, 2019, 3:43pm UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/9 "2019-11-29T15:43:46Z")

</div>

> [@nlordell](#):
>
> I think what I was looking for in my particular case was to use `PhantomData<Box<T>>` or similar to allow both the ability to use a type's associated functions and also always be `Unpin` .

That sounds super weird, because associated functions with a `self` argument (a.k.a. "methods") obviously can't be invoked if there is no actual `self`/`T` value to pass to them (and `PhantomData<T>` doesn't contain an actual `T`), but associated functions without one can be trivially invoked from anywhere as `T::foo()` (so there's no reason to get `PhantomData` involved).

Is there something else I'm missing, or was this just confusion?

---

<div class="post-metadata">

**Author:** ![ExpHP](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/exphp/32/6208_2.png) [@ExpHP](https://internals.rust-lang.org/u/ExpHP)\
**Post date:** [November 29, 2019, 9:16pm UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/10 "2019-11-29T21:16:52Z")

</div>

Though the precise semantics of `Unpin` still melt my mind, I imagine this trait bound actually serves a useful purpose, since it does so for other auto traits. Basically, `impl !Trait for T` is still unstable, but you can simulate it by adding PhantomData members. That is,

```rust
#[repr(transparent)]
struct NoSyncI32 {
    value: i32,
    _no_sync: PhantomData<Cell<()>>,
}

```

is a wrapper around `i32` that disables the `Sync` `impl`. Perhaps there are use cases for similarly using `PhantomData` to disable `Unpin` impls.

**Edit:** Ah. Hm. No, there's a dedicated `PhantomPinned` for that, presumably because no standard library types impl `!Unpin`. Interesting. (However, `PhantomData` is still useful in generic impls in cases where the intent is to disable `Unpin` when `T: !Unpin`)

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [November 30, 2019, 3:11am UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/11 "2019-11-30T03:11:40Z")

</div>

IIRC trait objects lack all auto-traits, unless explicitly specified, so you could use something like `PhantomData<dyn Fn()>`.

---

<div class="post-metadata">

**Author:** ![nlordell](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nlordell/32/6306_2.png) [@nlordell](https://internals.rust-lang.org/u/nlordell)\
**Post date:** [November 30, 2019, 8:52am UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/12 "2019-11-30T08:52:15Z")

</div>

> @Ixrec: Is there something else I'm missing, or was this just confusion?

The idea was I needed something to be `Unpin` that looked like:

```rust
struct Foo<T: Bar> {
    _bar: PhantomData<Box<T>>,
}

```

So that `Foo` could be generic over `T` for calling `T::bar()`. If I used just `PhantomData<T>` then `Foo` would only be `Unpin` if `T: Unpin`. Using `PhantomData<Box<T>>` allowed `Foo` to be `Unpin` regardless of `T` which is what we wanted in this case, since T is just used for the associated method `T::bar()`. I hope this clarifies things...

---

<div class="post-metadata">

**Author:** ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)\
**Post date:** [November 30, 2019, 12:52pm UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/13 "2019-11-30T12:52:19Z")

</div>

Ah, that does make more sense. I still think wrappers like this are usually cases where the type author needs to think about whether Unpin is appropriate, but I definitely see why that wouldn't be nearly as obvious as, say, structs with a raw pointer and a PhantomData describing the pointee.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [February 28, 2020, 12:52pm UTC](https://internals.rust-lang.org/t/resolved-phantomdata-and-unpin/11393/14 "2020-02-28T12:52:25Z")

</div>

Closed on February 28, 2020, 12:52pm UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
