1//! Driving a future that never has to wait, on the spot. 2//! 3//! The native adapters block inside their `async fn`s (a file write, a blocking HTTP call), and the 4//! in-memory adapter does no waiting at all, so every future they make is `Ready` on its first poll. 5//! This runs such a future without an executor. It does NOT wait: a future that is `Pending` is a 6//! bug in the adapter (it would have needed a real executor), and this panics rather than spin. 7//! There is no thread, no clock and no I/O here, so it builds for a Worker; it is not what a Worker 8//! would use to run its own futures. 9 10use std::future::Future; 11use std::pin::pin; 12use std::task::{Context, Poll, Waker}; 13 14/// Runs `future` to completion, panicking if it ever returns `Pending`. 15pub fn run_ready<F: Future>(future: F) -> F::Output { 16 let mut future = pin!(future); 17 let mut cx = Context::from_waker(Waker::noop()); 18 match future.as_mut().poll(&mut cx) { 19 Poll::Ready(v) => v, 20 Poll::Pending => panic!("run_ready: a future that needed to wait was given to an executor that cannot"), 21 } 22} 23 24#[cfg(test)] 25mod tests { 26 use super::*; 27 28 #[test] 29 fn it_runs_a_future_that_is_ready() { 30 assert_eq!(run_ready(async { 1 + 2 }), 3); 31 } 32 33 #[test] 34 #[should_panic(expected = "needed to wait")] 35 fn it_refuses_a_future_that_must_wait() { 36 run_ready(std::future::pending::<()>()); 37 } 38}