async-trait
async-trait copied to clipboard
Unexpected "one type is more general than the other" compiler error
I have some async code with a collection of futures that I have called join_all on. It seems to work fine, but when I try to call that code call from an implementation from an #[async_trait], I am getting an error I don't quite understand;
error[E0308]: mismatched types
--> src/lib.rs:50:39
|
50 | async fn create_trait(&self) -> V {
| _______________________________________^
51 | | // This compiles
52 | | // self.create_impl_join_all().await
53 | | // This compiles
... |
56 | | self.create_impl_map_join_all().await
57 | | }
| |_____^ one type is more general than the other
|
= note: expected type `FnOnce<(V,)>`
found type `FnOnce<(V<Box<dyn std::fmt::Display + std::marker::Send>>,)>`
The below code compiles if either of the map or join_all are called, but fails with the above error if both map and join_all are used.
In addition
- changing
T = Box<dyn Display + Send>intoT = Box<usize>makes it compile - inlining the type, so
Vbecomespub struct V<T: ?Sized = dyn Display + Send + ?Sized> { _v: Box<T> }fails with the same message as above - inlining the type, so
Vbecomespub struct V { _v: Box<dyn Display + Send> }makes it compile
use async_trait::async_trait;
use futures::future::join_all;
use futures::FutureExt;
use std::fmt::Display;
pub struct V<T = Box<dyn Display + Send>> {
_v: T
}
fn create_v(n: usize) -> V {
V {
_v: Box::new(n)
}
}
async fn create_v_async(n: usize) -> V {
create_v(n)
}
pub struct Test {}
impl Test {
pub async fn create_impl_join_all(&self) -> V {
let future = create_v_async(42);
join_all(vec![future]).await.pop().unwrap()
}
pub async fn create_impl_map(&self) -> V {
let future = create_v_async(42)
.map(|rv| rv);
future.await
}
pub async fn create_impl_map_join_all(&self) -> V {
let future = create_v_async(42)
.map(|rv| rv);
join_all(vec![future]).await.pop().unwrap()
}
}
#[async_trait]
pub trait Trait<T> {
async fn create_trait(&self) -> T;
}
#[async_trait]
impl Trait<V> for Test {
async fn create_trait(&self) -> V {
// This compiles
// self.create_impl_join_all().await
// This compiles
// self.create_impl_map().await
// This fails to compile with a "one type is more general than the other" error
self.create_impl_map_join_all().await
}
}
Potentially related to #34 ?
getting a similar error for this code
--> crdt-enc-tokio/src/lib.rs:225:49
|
225 | ) -> Result<Vec<(Uuid, u64, VersionBytes)>> {
| _________________________________________________^
226 | | async fn get_entry(
227 | | path: &Path,
228 | | actor: Uuid,
... |
277 | | .await
278 | | }
| |_____^ one type is more general than the other
|
= note: expected opaque type `impl futures::Future`
found opaque type `impl futures::Future`
[email protected] seems to work for me, all newer versions (including 0.1.48) fail to build.
I am seeing the same error when trying to upgrade async-trait in https://github.com/pantsbuild/pants from v0.1.42 to v0.1.43 and newer (starts to happen in v0.1.43).
Compiling fs v0.0.1 (XXX/pants/src/rust/engine/fs)
error[E0308]: mismatched types
--> fs/src/lib.rs:691:95
|
691 | async fn path_stats(&self, paths: Vec<PathBuf>) -> Result<Vec<Option<PathStat>>, io::Error> {
| _______________________________________________________________________________________________^
692 | | future::try_join_all(
693 | | paths
694 | | .into_iter()
... |
715 | | .await
716 | | }
| |___^ one type is more general than the other
|
::: /Users/XXX/.rustup/toolchains/1.54.0-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/future/mod.rs:61:43
|
61 | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
| -------------------------------
| |
| the expected opaque type
| the found opaque type
|
= note: expected opaque type `impl futures::Future`
found opaque type `impl futures::Future`
I am seeing the same error when trying to upgrade
async-traitin https://github.com/pantsbuild/pants from v0.1.42 to v0.1.43 and newer (starts to happen in v0.1.43).
The above issue still reproduces in 0.1.53.
Updated output on newer rustc:
error: higher-ranked lifetime error
--> src/main.rs:50:39
|
50 | async fn create_trait(&self) -> V {
| _______________________________________^
51 | | // This compiles
52 | | // self.create_impl_join_all().await
53 | | // This compiles
... |
56 | | self.create_impl_map_join_all().await
57 | | }
| |_____^
|
= note: could not prove `Pin<Box<[async block@src/main.rs:50:39: 57:6]>>: CoerceUnsized<Pin<Box<(dyn futures::Future<Output = V<Box<(dyn std::fmt::Display + std::marker::Send + 'e)>>> + std::marker::Send + 'f)>>>`
This is a rustc bug that is already reported in https://github.com/rust-lang/rust/issues/82921.