Open
Description
In the case that an async trait fn returns a trait level generic T
, if that trait is implemented for multiple T
, the compiler complains that type annotations are needed (to specify T
) even though that type annotation is specified. It's suggestion is to try using a fully qualified path to specify the types. When the fully qualified trait::fn path is used, it does compile, but this is unnecessary and is not needed for the synchronous couterpart.
Code to reproduce with explanations in the comments.
trait Get<Item> {
// synchronous version for comparison
fn get_one(&self) -> Item {
todo!()
}
// asynchronous version which give the bug
async fn get_one_async(&self) -> Item {
todo!()
}
}
// Here's how it looks using the async_trait macro for earlier versions of rust. (This works)
#[async_trait::async_trait]
trait GetUsingAsyncTraitMacro<Item> {
async fn get_one_async_trait_macro(&self) -> Item {
todo!()
}
}
struct Getter;
struct Foo;
struct Bar;
// Impl Get<T> for multiple Get<T>
impl Get<Foo> for Getter {}
impl Get<Bar> for Getter {}
#[async_trait::async_trait]
impl GetUsingAsyncTraitMacro<Bar> for Getter {}
#[async_trait::async_trait]
impl GetUsingAsyncTraitMacro<Foo> for Getter {}
async fn demo() -> Result<(), ()> {
let mut getter = Getter;
// The synchronous version works fine
let item1: Bar = getter.get_one();
// The pre rust async fn in trait, async_trait::async_trait, works fine
let item3: Bar = getter.get_one_async_trait_macro().await;
// This has compiler error but it should not as type annotations are provided
let item2: Bar = getter.get_one_async().await;
//error[E0284]: type annotations needed
// = note: cannot satisfy `<foo::Getter as foo::Get<_>>::{opaque#0}<'_> == _`
// help: try using a fully qualified path to specify the expected types
// Try the fully qualified path:
// This compiler but is not ideal syntactically
let item2 = <Getter as Get<Bar>>::get_one_async(&getter).await;
Ok(())
}
The signatures of the sync and async fns are the same, so the code calling the async fn should compile if it works in the sync and async_trait cases.
Meta
rustc --version --verbose
:
rustc 1.75.0 (82e1608df 2023-12-21)
binary: rustc
commit-hash: 82e1608dfa6e0b5569232559e3d385fea5a93112
commit-date: 2023-12-21
host: x86_64-unknown-linux-gnu
release: 1.75.0
LLVM version: 17.0.6
rustc 1.77.0-nightly (62d7ed4a6 2024-01-11)
binary: rustc
commit-hash: 62d7ed4a6775c4490e493093ca98ef7c215b835b
commit-date: 2024-01-11
host: x86_64-unknown-linux-gnu
release: 1.77.0-nightly
LLVM version: 17.0.6
Backtrace
Compiling async-bug v0.1.0 (/tmp/async-bug)
error[E0284]: type annotations needed
--> src/main.rs:41:29
|
41 | let item2: Bar = getter.get_one_async().await;
| ^^^^^^^^^^^^^
|
= note: cannot satisfy `<Getter as Get<_>>::{opaque#0}<'_> == _`
help: try using a fully qualified path to specify the expected types
|
41 | let item2: Bar = <Getter as Get<Item>>::get_one_async(&getter).await;
| ++++++++++++++++++++++++++++++++++++++ ~
error[E0283]: type annotations needed
--> src/main.rs:41:29
|
41 | let item2: Bar = getter.get_one_async().await;
| ^^^^^^^^^^^^^
|
note: multiple `impl`s satisfying `Getter: Get<_>` found
--> src/main.rs:24:1
|
24 | impl Get<Foo> for Getter {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
25 |
26 | impl Get<Bar> for Getter {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: try using a fully qualified path to specify the expected types
|
41 | let item2: Bar = <Getter as Get<Item>>::get_one_async(&getter).await;
| ++++++++++++++++++++++++++++++++++++++ ~
Some errors have detailed explanations: E0283, E0284.
For more information about an error, try `rustc --explain E0283`.
error: could not compile `async-bug` (bin "async-bug") due to 2 previous errors