Skip to content

Tracking issue for Pin APIs (RFC 2349) #49150

Closed

Description

@withoutboats

Tracking issue for rust-lang/rfcs#2349

Blocking stabilization:

Unresolved questions:

  • Should we provide stronger guarantees around leaking !Unpin data?

Edit: Summary comment: #49150 (comment) (in the hidden-by-default part)

Activity

  1. added
    B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.
    T-libs-api[DEPRECATED; DO NOT USE]
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Mar 18, 2018
  2. Nemo157 commented on Mar 20, 2018

    @Nemo157
    Contributor

    I now notice that stack pinning is not part of the RFC, @withoutboats are you planning on releasing a crate for this, or should I just copy the example code into my crate that needs it?

  3. withoutboats commented on Mar 21, 2018

    @withoutboats
    ContributorAuthor

    @Nemo157 You should copy it and report your experience!

    The unresolved question about leaking Unpin data relates to this. That API is unsound if we say you cannot overwrite Unpin data in a Pin unless the destructor runs, as @cramertj requested. There are other, less ergonomic, stack pinning APIs that do work for this. Its unclear what the right choice here is - is the ergonomic stack pinning API more useful or is the extra guarantee about leaking more useful?

    One thing I'll note is that the stack pinning was not sufficient for things like Future::poll inside the await! macro, because it didn't allow us to poll in a loop. I'd be interested if you run into those issues, and how/if you solve them if you do.

  4. Nemo157 commented on Mar 21, 2018

    @Nemo157
    Contributor

    My current usage is pretty trivial, a single-threaded executor running a single StableFuture without spawning support. Switching to an API like @cramertj suggests would work fine with this. I have wondered how to extend this to allow spawning multiple StableFutures, but at least with my current project that's not necessary.

  5. valff commented on Mar 29, 2018

    @valff
    Contributor

    Just tried to experiment with the API. Looks like the following (suggested by RFC) definition of Future is no longer object-safe?

    trait Future {
        type Item;
        type Error;
    
        fn poll(self: Pin<Self>, cx: &mut task::Context) -> Poll<Self::Item, Self::Error>;
    }
  6. valff commented on Mar 29, 2018

    @valff
    Contributor

    Nevermind. Found a note about a plan to make arbitrary_self_types object-safe.

  7. RalfJung commented on Mar 29, 2018

    @RalfJung
    Member

    @withoutboats

    One thing I'll note is that the stack pinning was not sufficient for things like Future::poll inside the await! macro, because it didn't allow us to poll in a loop.

    Could you elaborate on that?

  8. cramertj commented on Mar 29, 2018

    @cramertj
    Member

    @RalfJung You need Pin to support reborrows as Pin, which it currently does not.

  9. RalfJung commented on Mar 30, 2018

    @RalfJung
    Member

    @cramertj That sounds like a restriction of the Pin API, not of the stack pinning API?

  10. cramertj commented on Mar 30, 2018

    @cramertj
    Member

    @RalfJung Yes, that's correct. However, PinBox can be reborrowed as Pin, while the stack-pinned type cannot (one borrow as Pin creates a borrow for the entire lifetime of the stack type).

  11. RalfJung commented on Mar 30, 2018

    @RalfJung
    Member

    Given a Pin, I can borrow it as &mut Pin and then use Pin::borrow -- that's a form of reborrowing. I take it that's not the kind of reborowing you are talking about?

  12. cramertj commented on Mar 30, 2018

    @cramertj
    Member

    @RalfJung No-- methods like Future::poll were planned to take self: Pin<Self>, rather than self: &mut Pin<Self> (which isn't a valid self type since it isn't Deref<item = Self> -- it's Deref<Item = Pin<Self>>).

  13. withoutboats commented on Mar 30, 2018

    @withoutboats
    ContributorAuthor

    It might be the case that we could get this to work with Pin::borrow actually. I'm not sure.

  14. 218 remaining items

  15. Pauan commented on Oct 23, 2018

    @Pauan

    @tikue @tmandry @withoutboats Thanks for the answers! It was very helpful.

  16. crlf0710 commented on Oct 28, 2018

    @crlf0710
    Member

    So what are the states of the two concerns now? (api-refactor & get_mut_unchecked_mut_mut) As someone who's eagerly waiting for the async/await series feature, I wonder which rustc version will the Pin APIs target? Is there an estimation?

  17. aturon commented on Nov 9, 2018

    @aturon
    Contributor
  18. added a commit that references this issue on Dec 12, 2018
  19. Centril commented on Dec 27, 2018

    @Centril
    Contributor

    @withoutboats Seems done? Shall we close?

  20. removed
    proposed-final-comment-periodProposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.
    disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.
    on Dec 27, 2018
  21. danielhenrymantilla commented on Feb 11, 2019

    @danielhenrymantilla
    Contributor

    Ok I apologise if this is not the place to post this, but I have been thinking about the Drop + !Unpin issue, and have come out with the following idea:

    1. Ideally, if Drop::drop was fn(self: Pin<&mut Self>) there would be no issue. Let's call such a Drop PinDrop. We cannot just replace Drop by PinDrop because of retrocompatibility issues.

    2. since the only issue with Drop::drop(&mut self) is for the Drop + !Unpin case, we could derive a default impl of PinDrop for Drop + Unpin (since then Pin<&mut T> : DerefMut<Target = T>) and make PinDrop be the trait automagically used by rustc (thanks to Pin::new_unchecked(&mut self), since drop is the only case of stack pinning when we think about it).

    Here is a sketchy PoC of the idea: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=9aae40afe732babeafef9dab3d7525a8

    Anyways, imho this should remain in beta and not go stable yet, even if it has to be an exception. If there is a time where Drop behavior can depend on Unpin without breaking compat then that time is now.

  22. RalfJung commented on Feb 11, 2019

    @RalfJung
    Member

    @danielhenrymantilla I don't see how that solves the problem of compatibility with existing generic drop impls, like impl<T> Drop for Vec<T>.

  23. danielhenrymantilla commented on Feb 11, 2019

    @danielhenrymantilla
    Contributor

    You're right it requires another thing:
    an implicit T: Unpin bound on all generics, with an opt-out using ?Unpin in the same manner as Sized

    That should make it become

    impl<T> Drop for Vec<T>
    where
      T : Unpin, // implicit, which implies that Vec<T> : Unpin which "upgrades" `Drop` into `PinDrop`
    
  24. RalfJung commented on Feb 11, 2019

    @RalfJung
    Member

    an implicit T: Unpin bound on all generics, with an opt-out using ?Unpin in the same manner as Sized

    This has a huge effect on the overall API design, and was discussed extensively as part of the ?Move proposals. For example, it would mean that many, many existing libraries would need updating to work with pinning. The conclusion was that going with a library-only solution such as what we got now is better because it requires none of this.

  25. danielhenrymantilla commented on Feb 11, 2019

    @danielhenrymantilla
    Contributor

    Yep, huge cost short term since all existing libraries would need to update to be !Unpin compatible, but in the long run we would end up with a "safer" Drop. It did not seem that bad at first, since at least we are not breaking anything.

    But it is a fair concern (I did not know that it had been raised previously; thank you for pointing it out, @RalfJung ), and I guess that the short term practical drawbacks do out-weight the little safety gain of a drop(Pin<&mut Self>).

  26. shanemikel commented on Apr 23, 2019

    @shanemikel

    Has there been any discussion on Hash implementation for Pin types hashing on addresses?

  27. Nemo157 commented on Apr 23, 2019

    @Nemo157
    Contributor

    Pin should probably have an implementation of Hash that simply delegates to the contained pointer, there's no precedence for hashing based on addresses (and I don't see any reason that pinning a value should change how it gets hashed).

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

    B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCT-langRelevant to the language teamT-libs-api[DEPRECATED; DO NOT USE]

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions