send_future/lib.rs
1#![no_std]
2
3//! This crate provides [`SendFuture::send`] workaround for compiler bug
4//! [https://github.com/rust-lang/rust/issues/96865](https://github.com/rust-lang/rust/issues/96865)
5//!
6//! See documentation of [`SendFuture`] trait for example usage
7
8/// This trait is used as a workaround for compiler bug
9/// [https://github.com/rust-lang/rust/issues/96865](https://github.com/rust-lang/rust/issues/96865)
10///
11/// Compilation of code calling async methods defined using `impl` syntax within [`Send`] async functions
12/// may fail with hard-to-debug errors.
13///
14/// The following fails to compile with rustc 1.78.0:
15///
16/// ```compile_fail
17/// trait X {
18/// fn test<Y>(&self, x: impl AsRef<[Y]>) -> impl core::future::Future<Output = ()> + Send
19/// where
20/// Y: AsRef<str>;
21/// }
22
23/// fn call_test(x: impl X + Send + Sync) -> impl core::future::Future<Output = ()> + Send {
24/// async move { x.test(["test"]).await }
25/// }
26/// ```
27///
28/// ```text
29/// error: implementation of `AsRef` is not general enough
30/// --> src/lib.rs:66:9
31/// |
32/// 66 | async move { x.test(["test"]).await }
33/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `AsRef` is not general enough
34/// |
35/// = note: `[&'0 str; 1]` must implement `AsRef<[&'1 str]>`, for any two lifetimes `'0` and `'1`...
36/// = note: ...but it actually implements `AsRef<[&str]>`
37/// ```
38///
39/// The fix is to call [`send`](SendFuture::send) provided by this trait on the future before awaiting:
40/// ```
41/// use send_future::SendFuture as _;
42///
43/// trait X {
44/// fn test<Y>(&self, x: impl AsRef<[Y]>) -> impl core::future::Future<Output = ()> + Send
45/// where
46/// Y: AsRef<str>;
47/// }
48
49/// fn call_test(x: impl X + Send + Sync) -> impl core::future::Future<Output = ()> + Send {
50/// async move { x.test(["test"]).send().await }
51/// }
52/// ```
53pub trait SendFuture: core::future::Future {
54 fn send(self) -> impl core::future::Future<Output = Self::Output> + Send
55 where
56 Self: Sized + Send,
57 {
58 self
59 }
60}
61
62impl<T: core::future::Future> SendFuture for T {}
63
64#[allow(unused)]
65#[cfg(test)]
66mod tests {
67 use super::SendFuture as _;
68
69 trait X {
70 fn test<Y>(&self, x: impl AsRef<[Y]>) -> impl core::future::Future<Output = ()> + Send
71 where
72 Y: AsRef<str>;
73 }
74
75 fn call_test(x: impl X + Send + Sync) -> impl core::future::Future<Output = ()> + Send {
76 async move { x.test(["test"]).send().await }
77 }
78}