makepad/libs/relax/compiler/tests/async_pin_dyn.rs
Admin b22a714840 makepad run: the Rust JIT (libs/relax) and makepad-remote
The JIT that runs makepad apps from source: lexer, front end, type checker,
lazy borrow checker (Gandalf; `--check-first` opts in), codegen, session and
warm/cold caches keyed by compiler stamp, provided crates bound late,
startup images, live patching. User-facing name is `makepad run` (binary
`makepad`, MAKEPAD_RUN_* env, ~/.makepad-run); libs/relax stays the internal
library name. `makepad check` reports rustc-style diagnostics with rustc
error codes and checks a whole workspace (`--workspace`). Runs on macOS,
Linux, Windows and Android. makepad-remote: one tool schema for apps and the
WM (app/1): grabs, captures, traces, frame profiles and tweaks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 12:26:21 +02:00

82 lines
2.4 KiB
Rust

// `Pin<&mut dyn Future>`.poll(cx) is the trait object's poll (rustc's probe matches the
// `self: Pin<&mut Self>` receiver with Self = dyn Future), not Pin's own Future impl; boxed
// trait-object futures, async recursion through them, `pin!`, async fns in traits.
use std::future::Future;
use std::pin::{pin, Pin};
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
fn noop_raw() -> RawWaker {
fn clone(_: *const ()) -> RawWaker { noop_raw() }
fn noop(_: *const ()) {}
static VT: RawWakerVTable = RawWakerVTable::new(clone, noop, noop, noop);
RawWaker::new(std::ptr::null(), &VT)
}
fn block_on<F: Future>(f: F) -> F::Output {
let waker = unsafe { Waker::from_raw(noop_raw()) };
let mut cx = Context::from_waker(&waker);
let mut f = pin!(f);
loop {
if let Poll::Ready(v) = f.as_mut().poll(&mut cx) {
return v;
}
}
}
struct Yield(bool);
impl Future for Yield {
type Output = ();
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
if self.0 { Poll::Ready(()) } else { self.0 = true; Poll::Pending }
}
}
fn depth(n: u32) -> Pin<Box<dyn Future<Output = u32>>> {
Box::pin(async move {
if n == 0 {
return 1;
}
Yield(false).await;
depth(n - 1).await + 1
})
}
trait Store {
async fn get(&self, k: u32) -> u32;
}
struct S(u32);
impl Store for S {
async fn get(&self, k: u32) -> u32 {
Yield(false).await;
self.0 + k
}
}
async fn use_store<T: Store>(t: &T) -> u32 {
t.get(1).await + t.get(2).await
}
#[test]
fn p01_dyn_pin() {
let waker = unsafe { Waker::from_raw(noop_raw()) };
let mut cx = Context::from_waker(&waker);
let mut b: Pin<Box<dyn Future<Output = u32>>> = Box::pin(async { 7 });
println!("| {:?}", b.as_mut().poll(&mut cx));
let mut c: Pin<Box<dyn Future<Output = u32>>> = Box::pin(async { 8 });
println!("| {:?}", Pin::new(&mut c).poll(&mut cx));
println!("| {}", block_on(depth(5)));
let v: Vec<Pin<Box<dyn Future<Output = u32>>>> = vec![depth(0), depth(2), Box::pin(async { 40 })];
let mut t = 0;
for f in v {
t += block_on(f);
}
println!("| {}", t);
}
#[test]
fn p02_pin_macro_trait_async() {
let waker = unsafe { Waker::from_raw(noop_raw()) };
let mut cx = Context::from_waker(&waker);
let mut f = pin!(async { 5 });
println!("| {:?}", f.as_mut().poll(&mut cx));
println!("| {}", block_on(use_store(&S(10))));
}