Skip to content

PhantomData patterns table should include interactions with Send/Sync #320

Closed
@lilyball

Description

@lilyball

According to the PhantomData patterns table, there seems to be no difference between using e.g. *const T and fn() -> T. Both are covariant on T and have no lifetime. But there actually is a difference, which is that PhantomData<*const T> is not Send or Sync, whereas PhantomData<fn() -> T> is Send and Sync.

This is something that users can figure out by thinking about how PhantomData implements auto traits according to its T parameter, but this isn't explicitly called out in the nomicon (or in the std::marker::PhantomData docs) and so it's easy to forget. For example, I changed some code from PhantomData<T> to PhantomData<fn() -> T> specifically to avoid the drop check (my type doesn't own a T, but instead it can produce Ts). It just so happens that this makes my type Send and Sync too, which it should have been in the first place but nobody realized that until well after the change.

This could be improved by updating the Nomicon to call out the fact that PhantomData will implement auto traits according to its type parameter, and to give an example of this by including Send/Sync columns in the table that lists whether the given pattern is Send/Sync. This would look something like

Phantom type 'a T Send Sync
PhantomData<T> - covariant (with drop check) T: Send T: Sync
PhantomData<&'a T> covariant covariant T: Sync T: Sync
PhantomData<&'a mut T> covariant invariant T: Send T: Sync
PhantomData<*const T> - covariant - -
PhantomData<*mut T> - invariant - -
PhantomData<fn(T)> - contravariant Send Sync
PhantomData<fn() -> T> - covariant Send Sync
...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions