Higher ranked lifetime error when tryng to see that a future is send. #114046
Open
Description
opened on Jul 25, 2023
I tried this code:
use std::marker::PhantomData;
trait Callable<'a>: Send + Sync {
fn callable(data: &'a [u8]);
}
trait Getter<'a>: Send + Sync {
type ItemSize: Send + Sync;
fn get(data: &'a [u8]);
}
struct List<'a, A: Getter<'a>> {
data: &'a [u8],
item_size: A::ItemSize, // Removing this member causes the code to compile
phantom: PhantomData<A>,
}
struct GetterImpl<'a, T: Callable<'a> + 'a> {
p: PhantomData<&'a T>,
}
impl<'a, T: Callable<'a> + 'a> Getter<'a> for GetterImpl<'a, T> {
type ItemSize = ();
fn get(data: &'a [u8]) {
<T>::callable(data);
}
}
struct ConstructableImpl<'a> {
_data: &'a [u8],
}
impl<'a> Callable<'a> for ConstructableImpl<'a> {
fn callable(_: &'a [u8]) {}
}
struct StructWithLifetime<'a> {
marker: &'a PhantomData<u8>,
}
async fn async_method() {}
fn assert_send(_: impl Send + Sync) {}
// This async method ought to be send, but is not
async fn my_send_async_method(_struct_with_lifetime: &mut StructWithLifetime<'_>, data: &Vec<u8>) {
let _named = List::<'_, GetterImpl<ConstructableImpl<'_>>> {
data,
item_size: (),
phantom: PhantomData,
};
assert_send(_named);
// Moving the await point above the constructed of _named, causes
// the method to become send, even though _named is Send + Sync
async_method().await;
}
fn dummy(struct_with_lifetime: &mut StructWithLifetime<'_>, data: &Vec<u8>) {
assert_send(my_send_async_method(struct_with_lifetime, data));
}
fn main() {}
I expect this code to compile successfully. However the compiler fails to infer that my_send_async_method
is SEND, even though it is.
I get the following error message:
$ rustc --version
rustc 1.71.0 (8ede3aae2 2023-07-12)
$ RUST_BACKTRACE=1 cargo build
Compiling minimal v0.1.0 (/home/jakobt/dev/minimal)
error: implementation of `Getter` is not general enough
--> src/main.rs:63:5
|
63 | assert_send(my_send_async_method(struct_with_lifetime, data));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Getter` is not general enough
|
= note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`...
= note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2`
error: implementation of `Callable` is not general enough
--> src/main.rs:63:5
|
63 | assert_send(my_send_async_method(struct_with_lifetime, data));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Callable` is not general enough
|
= note: `Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`...
= note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1`
error: higher-ranked lifetime error
--> src/main.rs:63:5
|
63 | assert_send(my_send_async_method(struct_with_lifetime, data));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: could not prove `impl Future<Output = ()>: Sync`
error: could not compile `minimal` (bin "minimal") due to 3 previous errors
This does not make sense, GetterImpl (and ConstructableImpl) cannot possible be constructed with two different lifetimes since that goes against the definition.
If we remove the call to async_method().await
The assert_send(_named)
show that _named is indeed Send
and Sync
, so the method should also me.
I have minimized this example as much as I can, removing any of the current parts resolves the issue. Removing the lifetime on StructWithLifetime
, does not resolve the issue but changes the error message to
error: higher-ranked lifetime error
--> src/main.rs:61:5
|
61 | assert_send(my_send_async_method(struct_with_lifetime, data));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: could not prove `impl Future<Output = ()>: Send`
error: higher-ranked lifetime error
--> src/main.rs:61:5
|
61 | assert_send(my_send_async_method(struct_with_lifetime, data));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: could not prove `impl Future<Output = ()>: Sync`
Metadata
Assignees
Labels
Area: Async & AwaitArea: Higher-ranked things (e.g., lifetimes, types, trait bounds aka HRTBs)Async-await issues that have been triaged during a working group meeting.Category: This is a bug.Relevant to the compiler team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.
Activity