pub type StepFuture<'a> = Pin<Box<dyn Future<Output = Result<(), Error>> + 'a>>;Expand description
A future returned by a migration step — boxed so Migration stays
object-safe (the runner holds Box<dyn Migration<X>>).
§This future is not Send, and cannot be made so on stable
Everywhere else in this crate Send-ness leaks: repo:: and
Query return unboxed futures, so theirs are Send
exactly when the concrete executor’s are — no bound declared, and both a
multi-threaded server and a single-threaded Worker are served by one
implementation.
Boxing behind dyn destroys that, because Box<dyn Future> is !Send
whatever was boxed. The bound would have to be written here — and it cannot
be satisfied: CreateTable implements Migration<X> for every
X: Executor, so its up would have to produce a Send future for every
executor, and whether X::execute’s future is Send is unknowable in a
generic context. Expressing it needs return-type notation
(X: Executor<execute(..): Send>), still unstable.
So Migrator::run is the one API here that cannot be awaited inside a
tokio::spawned task. Two ways round it, both fine in practice:
- Run migrations outside a spawned task — at boot, on the main future. This is what most applications do anyway.
- Render synchronously and execute the strings yourself.
schema::schema_ddlandddl::Migration::renderare ordinary synchronous functions returningVec<String>, so a caller that needs aSendfuture can render first and then await plainexecutecalls — no boxed future anywhere.
tests/send_futures.rs asserts the Send property for everything that can
hold it, and documents this exception.
Aliased Type§
pub struct StepFuture<'a> { /* private fields */ }