Skip to content

Make async futures Unpin if they don't borrow anything across .awaits #82187

Open

Description

@jplatte

Am I missing something or could rustc in principle make the anonymous (return) type of async fn and async {} blocks implement Unpin (or maybe it should be "not implement !Unpin") if the body does not contain any borrows across .await points? I couldn't find an existing issue about this.

Activity

  1. JakobDegen commented on Feb 16, 2021

    @JakobDegen
    Contributor

    This seems like it would cause problems regarding accidental breaking changes. Changing a function to now borrow something across an await point is an incredibly easy change to accidentally make and would result in the Unpin impl being removed from the return type.

    An alternative would be to make it possible to explicitly mark that an async function/block should be Unpin (removing the possibility of an accidental breaking change). I don't see how to do this in function signatures without introducing an additional keyword though (pub unpin async fn or such) and that's probably not worth the effort.

  2. jplatte commented on Feb 16, 2021

    @jplatte
    ContributorAuthor

    @JakobDegen I don't see how Unpin would be different to Send and Sync in this regard.

  3. jplatte commented on Feb 16, 2021

    @jplatte
    ContributorAuthor

    function authors that want to make it Unpin can specify the return type as impl Future + Unpin manually

    You mean by making it a regular fn and wrapping the entire body in async move {}? I think a similar strategy could be used to create an attribute macro that asserts Send / Sync / Unpin for async fn (not sure about async blocks, can proc-macro attrs be used on expressions?), but doing it manually would be super annoying.

  4. jplatte commented on Feb 16, 2021

    @jplatte
    ContributorAuthor

    I guess I'll create that then 😄

  5. jplatte commented on Feb 16, 2021

    @jplatte
    ContributorAuthor

    The amount of code required is smaller than I expected. I've hardly tested it, but I think it should work: https://docs.rs/async_auto_traits/0.1

  6. jplatte commented on Feb 16, 2021

    @jplatte
    Author
  7. jplatte commented on Feb 17, 2021

    @jplatte
    ContributorAuthor

    Okay, let's move this discussion to an issue on https://github.com/jplatte/async_auto_traits.

    @hyd-dev I suggest hiding your previous two comments here.

  8. added
    AsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.
    on Feb 19, 2021
  9. Dylan-DPC commented on Jan 15, 2024

    @Dylan-DPC
    Member

    Closing this as it's better tracked in the https://github.com/jplatte/async_auto_traits/issues/1 issue, and it is better to have it contained in one issue instead of having 2 issues tracking it in different places

  10. jplatte commented on Jan 15, 2024

    @jplatte
    ContributorAuthor

    @Dylan-DPC I think you misunderstood something, that is about preventing the leak of auto-traits of async fn future types. It only relates to Unpin in that it would sometime be useful to be able to stop leaking an Unpin implementation in a public interface if the compiler generated those impls at all (which this issue is about).

  11. djc commented on Sep 17, 2024

    @djc
    Contributor

    I was experimenting today with replacing the likes of futures_util::future::ok() (which is IMO a little ugly -- it reeks of the futures 0.1 times) with async move {} blocks and was surprised that I needed an explicit pin!() call wrapped around the async move {} block even with trivial Copy types (like usize).

  12. kayabaNerve commented on Nov 10, 2025

    @kayabaNerve

    I ran into this, unfortunately. While I completely understand the commentary on it being too prone to accidentally breaking changes, I'd love if if it was explicitly marked, then Unpin would be eligible to propagate up the library.

    One note is I don't have Unpin async blocks though. I have async blocks which are naturally Unpin if their generics are Unpin. I accordingly can't guarantee the returned future is Unpin. For my use-case, I'd need that conditional to be modelled.

  13. arthurp commented on Mar 10, 2026

    @arthurp

    A note for people who run into this: Coroutines do not have this limitation. I've heard that is unlikely to become stable, but it's worth knowing about.

    (BTW, I ran into this issue while trying to poll a future once before scheduling it (for performance reasons). This works, but you are forced to allocate a Box even if the future completes in the first poll call, since you can't move the future from the stack to the heap after the poll. Whether this matters in my context is an open question, but the limitation is still interesting.)

  14. theemathas commented on Mar 11, 2026

    @theemathas
    Contributor

    (Hypothetical) Unpin async futures and (existing on nightly) Unpin coroutines have a soundness issue: #153688

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-async-awaitArea: Async & AwaitAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.C-feature-requestCategory: A feature request, i.e: not implemented / a PR.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions