Closed
Description
Just like a lot of lifetime issues, I'm not actually sure whether this is a bug in the compiler or a bug in my code.
The following code:
use std::pin::Pin;
use std::future::Future;
trait FooRef<'a> {
type Elem;
fn next_elem(self) -> Pin<Box<dyn Future<Output = Self::Elem> + Send + Sync + 'a>>;
}
struct FooImpl;
impl<'a> FooRef<'a> for &'a mut FooImpl {
type Elem = &'a mut FooImpl;
fn next_elem(self) -> Pin<Box<dyn Future<Output = Self::Elem> + Send + Sync + 'a>> {
Box::pin(async move { self })
}
}
async fn run<F>(mut foo: F)
where for<'r> &'r mut F: FooRef<'r>
{
loop {
foo.next_elem().await;
}
}
fn test() {
fn req<T: Send>(_: T) {}
req(run(FooImpl))
}
Triggers the following compilation error:
error: implementation of `FooRef` is not general enough
--> src/lib.rs:29:5
|
29 | req(run(FooImpl))
| ^^^
|
= note: `FooRef<'1>` would have to be implemented for the type `&'0 mut FooImpl`, for any two lifetimes `'0` and `'1`
= note: but `FooRef<'2>` is actually implemented for the type `&'2 mut FooImpl`, for some specific lifetime `'2`
Replacing T: Send
with just T
makes it compile fine.
Replacing async fn run<F>(mut foo: F)
with async fn run(mut foo: FooImpl)
(ie. removing the generic parameter) also works fine.
Code explanation: calling foo.next_elem()
return a Future
that should keep foo
borrowed, and produces an element (type Elem;
) that still keeps foo
borrowed.
I don't really see the relationship between this behaviour and Send
. All the types used in this code do implement Send
.
My compiler version is rustc 1.39.0-nightly (c6e9c76c5 2019-09-04)
.