Skip to content

Commit e565329

Browse files
committed
Add error code documentation
1 parent a767877 commit e565329

File tree

4 files changed

+82
-2
lines changed

4 files changed

+82
-2
lines changed

src/librustc_error_codes/error_codes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ E0700: include_str!("./error_codes/E0700.md"),
381381
E0701: include_str!("./error_codes/E0701.md"),
382382
E0704: include_str!("./error_codes/E0704.md"),
383383
E0705: include_str!("./error_codes/E0705.md"),
384+
E0706: include_str!("./error_codes/E0706.md"),
384385
E0712: include_str!("./error_codes/E0712.md"),
385386
E0713: include_str!("./error_codes/E0713.md"),
386387
E0714: include_str!("./error_codes/E0714.md"),
@@ -595,7 +596,6 @@ E0744: include_str!("./error_codes/E0744.md"),
595596
E0696, // `continue` pointing to a labeled block
596597
// E0702, // replaced with a generic attribute input check
597598
E0703, // invalid ABI
598-
E0706, // `async fn` in trait
599599
// E0707, // multiple elided lifetimes used in arguments of `async fn`
600600
E0708, // `async` non-`move` closures with parameters are not currently
601601
// supported
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
`async fn`s are not yet supported 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 normally return an `impl Future`, making the following two examples equivalent:
14+
15+
```edition2018,ignore (example-of-desugaring-equivalence)
16+
async fn foo() -> User {
17+
unimplemented!()
18+
}
19+
// The async fn above gets desugared as follows:
20+
fn foo(&self) -> impl Future<Output = User> + '_ {
21+
unimplemented!()
22+
}
23+
```
24+
25+
But when it comes to supporting this in traits, there are [a few implementation
26+
issues][async-is-hard], one of which is that returning `impl Trait` in traits is not supported,
27+
as it would require [Generic Associated Types] to be supported:
28+
29+
```edition2018,ignore (example-of-desugaring-equivalence)
30+
impl MyDatabase {
31+
async fn get_user(&self) -> User {
32+
unimplemented!()
33+
}
34+
}
35+
36+
impl MyDatabase {
37+
fn get_user(&self) -> impl Future<Output = User> + '_ {
38+
unimplemented!()
39+
}
40+
}
41+
```
42+
43+
Until these issues are resolved, you can use the [`async-trait` crate], which allows you to use
44+
this feature by sidesteping the language feature issue by desugaring to "boxed futures"
45+
(`Pin<Box<dyn Future + Send + 'async>>`):
46+
47+
```edition2018,ignore (example-of-desugaring-equivalence)
48+
#[async_trait]
49+
impl MyDatabase {
50+
async fn get_user(&self) -> User {
51+
unimplemented!()
52+
}
53+
}
54+
55+
// The annotated impl above gets desugared as follows:
56+
impl MyDatabase {
57+
fn get_user<'async>(
58+
&'async self,
59+
) -> Pin<Box<dyn std::future::Future<Output = User> + Send + 'async>>
60+
where
61+
Self: Sync + 'async,
62+
{
63+
unimplemented!()
64+
}
65+
}
66+
```
67+
68+
Note that using these trait methods will result in a heap allocation per-function-call. This is not
69+
a significant cost for the vast majority of applications, but should be considered when deciding
70+
whether to use this functionality in the public API of a low-level function that is expected to be
71+
called millions of times a second.
72+
73+
You might be interested in visiting the [async book] for further information.
74+
75+
[`async-trait` crate]: https://crates.io/crates/async-trait
76+
[async-is-hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/
77+
[Generic Associated Types]: https://github.com/rust-lang/rust/issues/44265
78+
[async book]: https://rust-lang.github.io/async-book/07_workarounds/06_async_in_traits.html

src/test/ui/async-await/async-trait-fn.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ LL | async fn bar(&self) {}
1818

1919
error: aborting due to 2 previous errors
2020

21+
For more information about this error, try `rustc --explain E0706`.

src/test/ui/async-await/edition-deny-async-fns-2015.stderr

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,5 @@ LL | async fn foo() {}
6363

6464
error: aborting due to 10 previous errors
6565

66-
For more information about this error, try `rustc --explain E0670`.
66+
Some errors have detailed explanations: E0670, E0706.
67+
For more information about an error, try `rustc --explain E0670`.

0 commit comments

Comments
 (0)