Skip to content

Pinning non-Deref pointers #54815

@withoutboats

Description

@withoutboats
Contributor

Currently, you cannot even construct a Pin unless the pointer it wraps implements Deref. This means you cannot have a Pin<*const T>, Pin<*mut T> or Pin<NonNull<T>>. We should consider extending the API of Pin to support these constructs.

Unfortunately, I don't know if there's much this actually helps, because we have no unsafe equivalent of Deref as a trait abstraction. As a result, I think the only APIs that could apply to these pointers generically is:

  • unsafe fn new_unchecked(p: P) -> Pin<P>
  • unsafe fn into_inner(self: Pin<P>) -> P

This limits the utility of Pin on these pointers, since it basically guarantees nothing with this API.

If we had an UnsafeAsRef trait, we could support unsafe equivalents of as_ref and as_mut, allowing you to at least maintain the pinning invariant in your unsafe code. In other words, some sort of UnsafeAsRef and UnsafeAsMut traits would be necessary for this to actually be helpful. I'm not sure if those traits are worth adding.

Activity

added
T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.
on Oct 4, 2018
withoutboats

withoutboats commented on Oct 4, 2018

@withoutboats
ContributorAuthor
withoutboats

withoutboats commented on Oct 4, 2018

@withoutboats
ContributorAuthor

I have a pointer right now which is supposed to be sematically a Pin<NonNull<T>>:

  1. It upholds the pinning invariant on its inner data.
  2. It will never be null.
  3. It may dangle.

In practice what I do is this:

  • I have some APIs which take Pin<&T>, these APIs are safe.
  • I actually store a NonNull<T>, and convert it to a Pin<&T> when I call those APIs.

This means the pinning invariant could be broken anywhere in my code that can see the NonNull<T>. If I could store it as a Pin<NonNull<T>>, that code would only be responsible for making sure it never calls those safe APIs with a dangling pointer.

(FWIW the pinning invariant is important in this code because T contains an intrusive doubly linked list, rather than self-referential structures.)

RalfJung

RalfJung commented on Oct 5, 2018

@RalfJung
Member

In other words, some sort of UnsafeAsRef and UnsafeAsMut traits would be necessary for this to actually be helpful. I'm not sure if those traits are worth adding.

An alternative might be to have a dedicated trait just for Pin. I'd prefer that anyway to make sure people explicitly opt-in to pinning support with their types. Would that help?

added
C-enhancementCategory: An issue proposing an enhancement or a PR with one.
T-typesRelevant to the types team, which will review and decide on the PR/issue.
and removed
T-typesRelevant to the types team, which will review and decide on the PR/issue.
on Nov 18, 2023
paxbun

paxbun commented on Apr 13, 2024

@paxbun

We also need this feature. We have many types that are elements of a huge graph (or a tree). To avoid excessive use of RC smart pointers, the children of each node are stored in a type wrapping a vector, which ensures that the elements are pinned and cannot be moved (The iterator of that type also returns Pin<&mut T>), and We're using NonNull internally to represent cross edges or parents.
Using NonNull so means that the pointee is also pinned, and they're also exposed as &T or Pin<&mut T>. This kind of code needs a lot of conversions from NonNull to Pin<&mut T> or vice versa, but Pin<&mut T> to NonNull conversion results in verbose code.

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-pinArea: PinC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @Enselic@RalfJung@withoutboats@paxbun

        Issue actions

          Pinning non-Deref pointers · Issue #54815 · rust-lang/rust