pub trait AsyncHostedDep:
Sized
+ Send
+ Sync
+ 'static {
// Required methods
fn descriptor(&self) -> Vec<u8> ⓘ;
fn from_descriptor(bytes: &[u8]) -> impl Future<Output = Self> + Send;
}Expand description
Async counterpart of HostedDep. Implement this when worker-side
reconstruction needs to .await (e.g. opening async network
clients, doing async filesystem work, calling
Provided*::new(...).await constructors).
No opt-in flag is required: the helper functions emitted by
#[test_dep(scope = Hosted)] auto-select the async path under the tokio
runtime, so simply implementing AsyncHostedDep is enough.
#[test_dep(scope = Hosted)]
async fn dependencies() -> EnvBasedTestDependencies { /* … */ }
impl test_r::core::AsyncHostedDep for EnvBasedTestDependencies {
fn descriptor(&self) -> Vec<u8> { /* … */ }
async fn from_descriptor(bytes: &[u8]) -> Self { /* … */ }
}AsyncHostedDep is the tokio-only async counterpart of
HostedDep. Under the tokio test runtime the Hosted helper
functions emitted by #[test_dep(scope = Hosted)] always go
through AsyncHostedDep, regardless of whether the user wrote
impl HostedDep (covered by the blanket bridge below) or
impl AsyncHostedDep directly. Under the sync runtime, the same
helpers stay on HostedDep: a scope = Hosted registration that
uses an async-only AsyncHostedDep type therefore fails to
compile in sync builds. (Writing the impl on its own still compiles fine;
only the #[test_dep(scope = Hosted)] registration fails.)
descriptor() stays synchronous and is called on the parent owner
value, exactly as in HostedDep; the only difference is that
from_descriptor returns a Future so worker-side reconstruction
can await.
The legacy async_worker attribute is deprecated and ignored
(it now only triggers a compile-time deprecation warning at the
dep’s registration site); remove it from any new code.
Required Methods§
Sourcefn descriptor(&self) -> Vec<u8> ⓘ
fn descriptor(&self) -> Vec<u8> ⓘ
Owner-side: produce the descriptor bytes that workers will use to
reconstruct a connected handle. Called from the parent runner
process exactly once per Hosted dep, just like
HostedDep::descriptor.
Sourcefn from_descriptor(bytes: &[u8]) -> impl Future<Output = Self> + Send
fn from_descriptor(bytes: &[u8]) -> impl Future<Output = Self> + Send
Worker-side: asynchronously reconstruct a handle from descriptor bytes received from the parent.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementors§
impl<T> AsyncHostedDep for Twhere
T: HostedDep,
Blanket bridge: every HostedDep is automatically also an
AsyncHostedDep. The bridged from_descriptor returns
std::future::ready, so the bridge itself adds only an immediately-ready
future and the runtime can await all Hosted reconstruction uniformly.
This lets the test-r runtime drive every Hosted descriptor
reconstruction through one async path under the tokio runtime, regardless
of whether the dep’s own implementation is sync (impl HostedDep for ...)
or async (impl AsyncHostedDep for ...). The async_worker macro flag is
unnecessary — the implementor picks sync vs async purely at the trait-impl
call site.
Cost: the bridge itself is negligible (ready(x).await is an
immediately-ready future); when the runtime later routes every
Hosted reconstruction through the async path there is still a
small async-wrapper overhead per worker-startup-per-dep (polling
the outer future, and possibly one boxed-future allocation from
WorkerReconstructor::Async), but no extra user-level async work.
Coherence note: on stable Rust, with this blanket impl in place
a concrete type cannot manually implement both HostedDep and
AsyncHostedDep — rustc rejects that as conflicting
implementations. That compile-time error is the intended signal
that one of the two manual impls is redundant and should be
removed.
Source-compat note: if downstream code imports both
HostedDep and AsyncHostedDep into the same scope and calls
trait methods by method syntax (e.g.
MyType::from_descriptor(bytes) or dep.descriptor()), the call
can become ambiguous now that one type satisfies both traits.
Resolve with UFCS — <MyType as HostedDep>::from_descriptor(bytes).