Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
82 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
`async fn`s are not yet supported in Rust. | ||
|
||
Erroneous code example: | ||
|
||
```compile_fail,edition2018 | ||
trait T { | ||
// Neither case is currently supported. | ||
async fn foo() {} | ||
async fn bar(&self) {} | ||
} | ||
``` | ||
|
||
`async fn`s normally return an `impl Future`, making the following two examples equivalent: | ||
|
||
```edition2018,ignore (example-of-desugaring-equivalence) | ||
async fn foo() -> User { | ||
unimplemented!() | ||
} | ||
// The async fn above gets desugared as follows: | ||
fn foo(&self) -> impl Future<Output = User> + '_ { | ||
unimplemented!() | ||
} | ||
``` | ||
|
||
But when it comes to supporting this in traits, there are [a few implementation | ||
issues][async-is-hard], one of which is that returning `impl Trait` in traits is not supported, | ||
as it would require [Generic Associated Types] to be supported: | ||
|
||
```edition2018,ignore (example-of-desugaring-equivalence) | ||
impl MyDatabase { | ||
async fn get_user(&self) -> User { | ||
unimplemented!() | ||
} | ||
} | ||
impl MyDatabase { | ||
fn get_user(&self) -> impl Future<Output = User> + '_ { | ||
unimplemented!() | ||
} | ||
} | ||
``` | ||
|
||
Until these issues are resolved, you can use the [`async-trait` crate], which allows you to use | ||
this feature by sidesteping the language feature issue by desugaring to "boxed futures" | ||
(`Pin<Box<dyn Future + Send + 'async>>`): | ||
|
||
```edition2018,ignore (example-of-desugaring-equivalence) | ||
#[async_trait] | ||
impl MyDatabase { | ||
async fn get_user(&self) -> User { | ||
unimplemented!() | ||
} | ||
} | ||
// The annotated impl above gets desugared as follows: | ||
impl MyDatabase { | ||
fn get_user<'async>( | ||
&'async self, | ||
) -> Pin<Box<dyn std::future::Future<Output = User> + Send + 'async>> | ||
where | ||
Self: Sync + 'async, | ||
{ | ||
unimplemented!() | ||
} | ||
} | ||
``` | ||
|
||
Note that using these trait methods will result in a heap allocation per-function-call. This is not | ||
a significant cost for the vast majority of applications, but should be considered when deciding | ||
whether to use this functionality in the public API of a low-level function that is expected to be | ||
called millions of times a second. | ||
|
||
You might be interested in visiting the [async book] for further information. | ||
|
||
[`async-trait` crate]: https://crates.io/crates/async-trait | ||
[async-is-hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/ | ||
[Generic Associated Types]: https://github.com/rust-lang/rust/issues/44265 | ||
[async book]: https://rust-lang.github.io/async-book/07_workarounds/06_async_in_traits.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters