Skip to content

[BUG] calling async trait fn gives compiler error 'type annotations needed' when type annotation is already provided #119893

Open
@BaxHugh

Description

@BaxHugh

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inferenceArea: Type inferenceC-bugCategory: This is a bug.D-confusingDiagnostics: Confusing error or lint that should be reworked.S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions