Without boats, dreams dry up
When we developed the Pin API, our vision was that “ordinary users” - that is, users using the “high-level” registers of Rust, would never have to interact with it. We intended that only users implementing Futures by hand, in the “low-level” register, would have to deal with that additional complexity. And the benefit that would accrue to all users is that futures, being immovable while polling, could store self-references in their state.
Things haven’t gone perfectly according to plan. The benefits of Pin
have certainly been accrued -
everyone is writing self-referential async functions all the time, and low-level concurrency
primitives in all the major runtimes take advantage of Pin
to implement intrusive linked lists
internally. But Pin
still sometimes rears its ugly head into “high-level” code, and users are
unsurprisingly frustrated and confused when that happens.
In my experience, there a three main ways that this happens. Two of them can be solved by better
affordances for AsyncIterator
(a part of why I have been pushing stabilizing this so hard!). The
third is ultimately because of a mistake that we made when we designed Pin
, and without a breaking
change there’s nothing we could about it. They are:
Future
in a loop.Stream::next
.Future
behind a pointer (e.g. a boxed future).