Roughly:
When you want to read from files reactively, you run "select" with these files as arguments in a loop. The return value will tell you, which file is ready to be read.
In proactive IO, you instead supply a buffer to the read operation and get a handle back, that will notify you when the read operation is finished. Windows IO Completion Ports (IOCPs) are an example of this.
I am going to reason about this. It's me thinking aloud here.
I already know that JS callbacks and promises are somewhat equivalent to continuations. A continuation is something which is to be done later and which is passed as a value to functions which then directly or indirectly invoke the continuation or not if it is decided not to do the thing encapsulated in the continuation (for example if something failed and the algorithm is trying to bail out such that it doesn't make sense to continue with the continuation).
I also know that JS async/await is equivalent to generators. Koa version 1 used generators and Koa 2 switched to async/await.
I also know that Rust futures are or were based on generators. Rust generators are not stable and the last time I looked they were a bit left behind by futures. For me it seems that futures rely on some compiler magic such that they work even if generators are not stable.
Therefore Rust futures are somewhat equivalent to continuations.
There's a difference as far as I know, however. Continuations seem to be strictly more powerful than generators. In other words, you can implement generators by continuations but not the other way around.
It looks like the proactive IO in Bastion is using Rust's async/await, which I know nothing about, but in most languages async/await exists as sugar to make CPS look like linear flow.