logoalt Hacker News

yuriksyesterday at 2:25 PM1 replyview on HN

> Is this actually useful in practice?

It's required to do any intialization, particularly for compound futures (e.g. a "join" or "select" type of combinator), since you need to be able to move the future from where it's created to where it's eventually used/polled. I assume some of those cases could be subsumed by &uninit if that existed yeah.


Replies

amlutotoday at 3:35 AM

Passing an &uninit to a combinator seems like it would be strange.

But if you told me that some strongly typed language wanted to have coroutines and futures, that coroutine bodies would not execute at all until first polled, and that it was okay to move the thing you have before polling not the thing you had after polling, and I hadn’t seen Rust, I would maybe suggest:

1. Creating a Future (i.e. logically calling an async function) would return an object that is, conceptually, a NotYetPolledFuture. That object is movable or relocatable or whatever you call it (or it’s movable if and only if the parameters you passed are).

2. Later you exchange that object for a LiveFuture, which cannot be moved.

Rust has two limitations that would make this awkward:

- Rust doesn’t actually have immovable objects per se.

- The exchange is spelled fn exchange(val: Type1) -> Type2, which doesn’t work if Type2 is immovable.

But the &uninit/&own proposal in the OP is actually secretly a complex scheme using lifetimes to somewhat awkwardly do an in-place exchange from an uninitialized type to an initialized and owned type. Maybe that proposal could be extended a little bit to allow type exchanges. (Maybe it already does, sort of? You could pass an &uninit Future and a FutureToken and get out an &own Future, with the caveat that this would force the fields in the token to be moved unless the optimizer did something truly heroic.)