[BUG] calling async trait fn gives compiler error 'type annotations needed' when type annotation is already provided
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by extracting the reproducer from the issue into src/main.rs and run it with the listed stable and nightly rustc versions. Compare the async trait call with the synchronous and async_trait cases, then trace the compiler handling of the inferred trait generic and opaque async return type. Done means the annotated let item2: Bar = getter.get_one_async().await compiles without requiring a fully qualified path and regression coverage exists.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100