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