Skip to content

type inference fails when using async_fn_in_trait #108362

Open

Description

@LastExceed
#![feature(async_fn_in_trait)]

fn main() {}

trait MyTrait<T> {
	async fn foo(&mut self) -> T;
}


impl<T> MyTrait<bool> for T {
	async fn foo(&mut self) -> bool {
		true
	}
}

impl<T> MyTrait<i32> for T {
	async fn foo(&mut self) -> i32 {
		let x: bool = self.foo().await; //error[E0698]: type inside `async fn` body must be known in this context

		42
	}
}

works fine when removing async or using the async-trait crate

workaround:

let x: bool = MyTrait::<bool>::foo(self).await;

Activity

  1. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Feb 24, 2023
  2. compiler-errors commented on Jun 12, 2023

    @compiler-errors
    Contributor

    This issue isn't really related to async fn in trait itself, but more a limitation of opaque type inference (since opaques power async fn in trait):

    #![feature(impl_trait_in_assoc_type)]
    use core::future::Future;
    
    fn main() {}
    
    trait MyTrait<T> {
        type Foo<'a>: Future<Output = T> + 'a
        where
            Self: 'a;
    
        fn foo(&mut self) -> Self::Foo<'_>;
    }
    
    impl<T> MyTrait<bool> for T {
        type Foo<'a> = impl Future<Output = bool> + 'a
    	where
    		T: 'a;
    
        fn foo(&mut self) -> Self::Foo<'_> {
            async { true }
        }
    }
    
    impl<T> MyTrait<i32> for T {
        type Foo<'a> = impl Future<Output = i32> + 'a
    	where
    		T: 'a;
    
        fn foo(&mut self) -> Self::Foo<'_> {
            async {
                let x: bool = self.foo().await; //error[E0698]: type inside `async fn` body must be known in this context
                42
            }
        }
    }
  3. added
    A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.
    and removed on Jun 12, 2023
  4. compiler-errors commented on Sep 11, 2023

    @compiler-errors
    Contributor

    Actually, this is also just a limitation of the double indirection of async:

    use futures::future::LocalBoxFuture;
    use core::future::Future;
    
    fn main() {}
    
    trait MyTrait<T> {
        type Foo<'a>: Future<Output = T> + 'a
        where
            Self: 'a;
    
        fn foo(&mut self) -> Self::Foo<'_>;
    }
    
    impl<T> MyTrait<bool> for T {
        type Foo<'a> = LocalBoxFuture<'a, bool>
    	where
    		T: 'a;
    
        fn foo(&mut self) -> Self::Foo<'_> {
            Box::pin(async { true })
        }
    }
    
    impl<T> MyTrait<i32> for T {
        type Foo<'a> = LocalBoxFuture<'a, i32>
    	where
    		T: 'a;
    
        fn foo(&mut self) -> Self::Foo<'_> {
            Box::pin(async {
                let x: bool = self.foo().await; //error[E0698]: type inside `async fn` body must be known in this context
                42
            })
        }
    }
  5. compiler-errors commented on Sep 13, 2023

    @compiler-errors
    Contributor

    Actually, this isn't even a bug with AFIT. This is just an async bug:

    Details
    fn main() {}
    
    fn foo<T: Default>() -> T {
        T::default()
    }
    
    async fn bar() -> i32 {
        let x: bool = foo().await; //error[E0698]: type inside `async fn` body must be known in this context
        42
    }

    edit: see below

  6. added a commit that references this issue on Oct 14, 2023
  7. added
    WG-asyncWorking group: Async & await
    AsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.
    on Dec 18, 2023
  8. traviscross commented on Dec 18, 2023

    @traviscross
    Contributor

    We discussed this in the WG-async triage meeting. The feeling was that this may be difficult to fix and that it may be due to indirection introduced in the .await desugaring. To investigate further, someone might manually desugar .await to see where the ambiguity is originating.

    (Thanks in particular to @compiler-errors.)

  9. compiler-errors commented on Dec 18, 2023

    @compiler-errors
    Contributor

    I'm an idiot. The code I provided was just not well-formed. Let me look into this again I guess.

  10. Dylan-DPC commented on Jan 9, 2025

    @Dylan-DPC
    Member

    current output:

    error[E0284]: type annotations needed
      --> src/main.rs:18:22
       |
    18 |         let x: bool = self.foo().await; //error[E0698]: type inside `async fn` body must be known in this context
       |                            ^^^
       |
       = note: cannot satisfy `impl Future<Output = _> == _`
    help: try using a fully qualified path to specify the expected types
       |
    18 |         let x: bool = <T as MyTrait<T>>::foo(self).await; //error[E0698]: type inside `async fn` body must be known in this context
       |                       +++++++++++++++++++++++    ~
    
    error[E0283]: type annotations needed
      --> src/main.rs:18:22
       |
    18 |         let x: bool = self.foo().await; //error[E0698]: type inside `async fn` body must be known in this context
       |                            ^^^
       |
    note: multiple `impl`s satisfying `T: MyTrait<_>` found
      --> src/main.rs:10:1
       |
    10 | impl<T> MyTrait<bool> for T {
       | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...
    16 | impl<T> MyTrait<i32> for T {
       | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    help: try using a fully qualified path to specify the expected types
       |
    18 |         let x: bool = <T as MyTrait<T>>::foo(self).await; //error[E0698]: type inside `async fn` body must be known in this context
       |                       +++++++++++++++++++++++    ~
    
    Some errors have detailed explanations: E0283, E0284.
    For more information about an error, try `rustc --explain E0283`.
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

A-async-awaitArea: Async & AwaitA-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.A-inferenceArea: Type inferenceAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.WG-asyncWorking group: Async & await

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions