Yeah, the only Wrapper
created is 'b
, so I also don't see why it needs to be Send
for every lifetime. When I don't use a HRTB, but just demand <S as Source>::Wrapper<'b>
, I get:
Compiling playground v0.0.1 (/playground)
error: implementation of `Send` is not general enough
--> src/main.rs:48:5
|
48 | / {
49 | | let result = source.retrieve().await;
50 | | some_async_task().await;
51 | | result
52 | | }
| |_____^ implementation of `Send` is not general enough
|
= note: `<S as Source>::Wrapper<'0>` must implement `Send`, for any lifetime `'0`...
= note: ...but `Send` is actually implemented for the type `<S as Source>::Wrapper<'b>`
error: could not compile `playground` due to previous error
If you remember where, let me know…
I will try to boil it down further. Not sure if it will happen without the macro-expansion, but maybe it does. I think I somehow need to replace async-trait
's demand for Send
by creating an async
block with explicit type annotation or something like that (have done that for other examples I presented here).
Where exactly should I give that feedback best? The original issue is closed. I'm not very familiar with the exact proceedings, so if you can give me a hint where it's best to post it, I'd be thankful.
As for PR #89970, the direct impact wasn't too bad. PR #89970 did not really break anything. The problem with getting rid of the Send
bound in the associated type (Source::Wrapper<'_>
in my example) by adding a bound to the method (User::process
in my example) that uses that associated type wasn't possible before the update either, but error messages were different, I think. If I remember right, I got pages of errors with long lists of… I don't remember what it was, but it was worse .
However, PR #89970 resulted in the bloaty syntax of my code to de-sugar async trait methods to get bloated a bit more :
pub trait Binary: Sized {
type Dump<'a, 'b, W>: Future<Output = io::Result<()>> + Send
where
Self: 'a,
W: 'b;
fn dump<'a, 'b, W>(&'a self, writer: &'b mut W) -> Self::Dump<'a, 'b, W>
where
W: AsyncWrite + Unpin + Send;
type Restore<'a, R>: Future<Output = io::Result<Self>> + Send
where
R: 'a;
fn restore<'a, R>(reader: &'a mut R) -> Self::Restore<'a, R>
where
R: AsyncRead + Unpin + Send;
}
Luckily I can use a shorter notation without where
at least for implementation of that Binary
trait:
impl Binary for SomeStruct {
type Dump<'a, 'b, W: 'b> = impl Future<Output = io::Result<()>> + Send;
fn dump<'a, 'b, W>(&'a self, writer: &'b mut W) -> Self::Dump<'a, 'b, W>
where
W: AsyncWrite + Unpin + Send,
{
async move {
/* … */
}
}
type Restore<'a, R: 'a> = impl Future<Output = io::Result<Self>> + Send;
fn restore<'a, R>(reader: &'a mut R) -> Self::Restore<'a, R>
where
R: AsyncRead + Unpin + Send,
{
async move {
/* … */
}
}
}
It was ugly beforehand and still is ugly, so not a big issue. What bugs me most is the extra indentation due to the async move
, which is unrelated to PR #89970 and was necessary before.
Side note: If I get it right, such (ugly) desugaring might be necessary for a while when async trait methods shall guarantee to return a Send
able future. See also limitations/workarounds in the MVP of the async fn fundamentals initiative. But I'm happy that there is progress in getting support for async trait methods!