Info
This post is auto-generated from RSS feed The Rust Programming Language Forum - Latest topics. Source: About the deprecated continuation passing style futures
Hi, got a (historical) Rust question: the once-proposed CPS style Future
.
Recently I took a look at how Kotlin implemented its CPS coroutines; at first glance both Kotlin and Rust compile to state machines, but it quickly turns out Kotlin coroutines have some quirks that I'm not familiar with, so I decided to compare them against Rust more carefully. In particular, for Rust async
/.await
, Boats once gave a talk and some design processes behind the scene on this. Basically, Kotlin's CPS are ultimately callback functions stored somewhere and the state machine is for the callback to resume execution, i.e. a approach more akin to internal iteration. OTOH Rust settled for a more external iterator approach, for this way the interaction with lifetimes are better and various combinators may be implemented in a zero-cost way.
Now to the question. Boats mentioned that Rust once experimented with CPS style but gave up in the end, of which API is something like this:
trait Future {
type Output;
fn schedule(self, continuation: impl FnOnce(Self::Output));
}
My question is, why is the receiver self
, rather than &mut self
? In Kotlin terms, I guess this API correspond to the compiler generated invokeSuspend
for suspend fun
, but Kotlin isn't that good a reference in this case, for its GC nature and every non-primitive type is a reference: I cannot think of a direct Kotlin counterpart for a function of which receiver requires consuming itself...
My understanding is that when the CPS Future
is called (schedule
), it is then consumed. Since we still need its current internal states later, we need to put it somewhere, s.t. when the FnOnce
callback finally got invoked, it knows how/where to continue (the what part is already in its parameter). In other words, this API actually forces library authors to allocate, which is yet another reason why this approach doesn't play well with the zero-cost abstraction requirement. Is this the basic gist of it?
2 posts - 2 participants
🏷️ Rust_feed