You can write directly into the future (if you own it and know its structure), use a channel, etc. It's not the best ergonomics (see the comment uptree about this) but it's doable.
> This makes no sense, why would I ever want to do that?
Why would you ever want to wait on a Waker that you won't wake? :)
> That's a very big if. I said "easily" and this is not easy at all.
> Moreover it ignores the context: the SansIO/async/await code is generally a library written by a user, while the code that wants to use it is written by someone else entirely. Good luck sharing this external notion between the two!
It's not more difficult than with the manual state machine? That also has no general notion of inputs — you have to call specific functions to advance particular states with their inputs. There's no general equivalent of `poll`; the library and its caller have to agree on an API.
> I agree that it would be ideal to have a way to automatically generate the state machine from straightforward looking code, and async/await kinda does this, but this usecase requires more flexibility than what async/await provides.
I'm not trying to claim that (Rust's particular flavour of) async/await is suitable here. It certainly has some sharp edges, and it may well be that some of them bite for this project. I'd have loved to see an analysis of what and how, if so.
My point is just that use of async/await is not excluded by wanting to write some code ‘sans-I/O’. That's not a claim that it's universally applicable to all problems.