]>
Commit | Line | Data |
---|---|---|
60c5eb7d XL |
1 | `async fn`s are not yet supported in traits in Rust. |
2 | ||
3 | Erroneous code example: | |
4 | ||
5 | ```compile_fail,edition2018 | |
6 | trait T { | |
7 | // Neither case is currently supported. | |
8 | async fn foo() {} | |
9 | async fn bar(&self) {} | |
10 | } | |
11 | ``` | |
12 | ||
13 | `async fn`s return an `impl Future`, making the following two examples | |
14 | equivalent: | |
15 | ||
16 | ```edition2018,ignore (example-of-desugaring-equivalence) | |
17 | async fn foo() -> User { | |
18 | unimplemented!() | |
19 | } | |
20 | // The async fn above gets desugared as follows: | |
21 | fn foo(&self) -> impl Future<Output = User> + '_ { | |
22 | unimplemented!() | |
23 | } | |
24 | ``` | |
25 | ||
26 | But when it comes to supporting this in traits, there are [a few implementation | |
27 | issues][async-is-hard]. One of them is returning `impl Trait` in traits is not | |
28 | supported, as it would require [Generic Associated Types] to be supported: | |
29 | ||
30 | ```edition2018,ignore (example-of-desugaring-equivalence) | |
31 | impl MyDatabase { | |
32 | async fn get_user(&self) -> User { | |
33 | unimplemented!() | |
34 | } | |
35 | } | |
36 | ||
37 | impl MyDatabase { | |
38 | fn get_user(&self) -> impl Future<Output = User> + '_ { | |
39 | unimplemented!() | |
40 | } | |
41 | } | |
42 | ``` | |
43 | ||
44 | Until these issues are resolved, you can use the [`async-trait` crate], allowing | |
45 | you to use `async fn` in traits by desugaring to "boxed futures" | |
46 | (`Pin<Box<dyn Future + Send + 'async>>`). | |
47 | ||
48 | Note that using these trait methods will result in a heap allocation | |
49 | per-function-call. This is not a significant cost for the vast majority of | |
50 | applications, but should be considered when deciding whether to use this | |
51 | functionality in the public API of a low-level function that is expected to be | |
52 | called millions of times a second. | |
53 | ||
54 | You might be interested in visiting the [async book] for further information. | |
55 | ||
56 | [`async-trait` crate]: https://crates.io/crates/async-trait | |
57 | [async-is-hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/ | |
58 | [Generic Associated Types]: https://github.com/rust-lang/rust/issues/44265 | |
59 | [async book]: https://rust-lang.github.io/async-book/07_workarounds/06_async_in_traits.html |