From ee562ec2e5c52549f15755f0e200f7907b6f7c84 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Wed, 12 Nov 2025 09:55:22 -0800 Subject: [PATCH 1/2] Remove 'static constraint from block_on Factor out `spawn` into an unsafe helper `spawn_unchecked` where `block_on` can allow a non-static future and output to execute because dataflow ensures the Task does not outlive the future. Fixes #107 --- src/runtime/block_on.rs | 9 ++++++--- src/runtime/reactor.rs | 27 +++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/runtime/block_on.rs b/src/runtime/block_on.rs index 34f0dfa..c7bbd31 100644 --- a/src/runtime/block_on.rs +++ b/src/runtime/block_on.rs @@ -7,8 +7,7 @@ use std::task::{Context, Poll, Waker}; /// Start the event loop. Blocks until the future pub fn block_on(fut: F) -> F::Output where - F: Future + 'static, - F::Output: 'static, + F: Future, { // Construct the reactor let reactor = Reactor::new(); @@ -19,7 +18,11 @@ where } // Spawn the task onto the reactor. - let root_task = reactor.spawn(fut); + // Safety: The execution loop below, concluding with pulling the Ready out + // of the root_task, ensures that it does not outlive the Future or its + // output. + #[allow(unsafe_code)] + let root_task = unsafe { reactor.spawn_unchecked(fut) }; loop { match reactor.pop_ready_list() { diff --git a/src/runtime/reactor.rs b/src/runtime/reactor.rs index ba78fd9..32dc073 100644 --- a/src/runtime/reactor.rs +++ b/src/runtime/reactor.rs @@ -258,11 +258,17 @@ impl Reactor { ready } - /// Spawn a `Task` on the `Reactor`. - pub fn spawn(&self, fut: F) -> Task + /// We need an unchecked spawn for implementing `block_on`, where the + /// implementation does not expose the resulting Task and does not return + /// until all tasks have finished execution. + /// + /// # Safety + /// Caller must ensure that the Task does not outlive the Future F or + /// F::Output T. + #[allow(unsafe_code)] + pub(crate) unsafe fn spawn_unchecked(&self, fut: F) -> Task where - F: Future + 'static, - T: 'static, + F: Future, { let this = self.clone(); let schedule = move |runnable| this.inner.ready_list.lock().unwrap().push_back(runnable); @@ -278,6 +284,19 @@ impl Reactor { task } + /// Spawn a `Task` on the `Reactor`. + pub fn spawn(&self, fut: F) -> Task + where + F: Future + 'static, + T: 'static, + { + // Safety: 'static constraints satisfy the lifetime requirements + #[allow(unsafe_code)] + unsafe { + self.spawn_unchecked(fut) + } + } + pub(super) fn pop_ready_list(&self) -> Option { self.inner.ready_list.lock().unwrap().pop_front() } From 49f2f687966493446ac1af55cc7f1b4844ab16dc Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Wed, 12 Nov 2025 13:42:02 -0800 Subject: [PATCH 2/2] back up to rust 1.89 to see if that fixes wasm-ld segfault --- .github/workflows/ci.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 726a7cf..5d5708c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,6 +26,8 @@ jobs: - uses: actions/checkout@master - uses: ./.github/actions/install-rust + with: + toolchain: 1.89.0 - name: Install wasmtime uses: bytecodealliance/actions/wasmtime/setup@v1