Skip to main content

block_on

Function block_on 

Source
pub fn block_on<F>(fut: F) -> F::Output
where F: Future + Send, F::Output: Send,
Expand description

Sync-to-async bridge. Forwards to the shared multi-thread runtime’s block_on. Used by the TUI input loop and by App methods that need to wait on a crate::Pending from outside an async context.

Three execution contexts to handle:

  1. Non-tokio caller (sync main, sync test): no current handle, fall through to target.block_on(fut) directly.
  2. Multi-thread tokio caller (e.g. spawned task on the shared LSP runtime): relinquish the worker via [tokio::task::block_in_place] so other tasks keep running while we block on target.
  3. Non-multi-thread tokio caller (e.g. the editor actor’s dedicated current_thread runtime per slice 3c.final.E.swap): block_in_place panics here because the current runtime isn’t MultiThread; we instead escape to a fresh OS thread via std::thread::scope and drive the future on target from outside any tokio context.

The third case is the fix for slice 3c.fixup.actor-block-on: before this, block_on calls from inside the editor actor’s runtime (file save, document.dispatch_with_cancel, LSP completion-resolve, code-action apply, synthetic-buffer seed) panicked with “can call blocking only when running on the multi-threaded runtime” — caught only by cargo bench (release builds), not by cargo test (which preserves direct App.editor: Editor via the cfg(test) escape hatch and thus never spawns the actor).

Send bound: F: Send + F::Output: Send are required by std::thread::scope in the third case. Every existing caller satisfies these (Arc-backed handles, owned move-captures); if a future caller doesn’t, the type system catches it at the call site.