Rollup merge of #66526 - estebank:async-fn-trait-information, r=Centril
Add more context to `async fn` trait error Follow up to #65937. Fix #65899.
This commit is contained in:
commit
0a0d07a1fc
@ -383,6 +383,7 @@ E0700: include_str!("./error_codes/E0700.md"),
|
||||
E0701: include_str!("./error_codes/E0701.md"),
|
||||
E0704: include_str!("./error_codes/E0704.md"),
|
||||
E0705: include_str!("./error_codes/E0705.md"),
|
||||
E0706: include_str!("./error_codes/E0706.md"),
|
||||
E0712: include_str!("./error_codes/E0712.md"),
|
||||
E0713: include_str!("./error_codes/E0713.md"),
|
||||
E0714: include_str!("./error_codes/E0714.md"),
|
||||
@ -595,7 +596,6 @@ E0744: include_str!("./error_codes/E0744.md"),
|
||||
E0696, // `continue` pointing to a labeled block
|
||||
// E0702, // replaced with a generic attribute input check
|
||||
E0703, // invalid ABI
|
||||
E0706, // `async fn` in trait
|
||||
// E0707, // multiple elided lifetimes used in arguments of `async fn`
|
||||
E0708, // `async` non-`move` closures with parameters are not currently
|
||||
// supported
|
||||
|
57
src/librustc_error_codes/error_codes/E0706.md
Normal file
57
src/librustc_error_codes/error_codes/E0706.md
Normal file
@ -0,0 +1,57 @@
|
||||
`async fn`s are not yet supported in traits 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 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 them is 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], allowing you to use
|
||||
`async fn` in traits by desugaring to "boxed futures"
|
||||
(`Pin<Box<dyn Future + Send + 'async>>`).
|
||||
|
||||
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
|
@ -173,8 +173,11 @@ impl<'a> AstValidator<'a> {
|
||||
|
||||
fn check_trait_fn_not_async(&self, span: Span, asyncness: IsAsync) {
|
||||
if asyncness.is_async() {
|
||||
struct_span_err!(self.session, span, E0706,
|
||||
"trait fns cannot be declared `async`").emit()
|
||||
struct_span_err!(self.session, span, E0706, "trait fns cannot be declared `async`")
|
||||
.note("`async` trait functions are not currently supported")
|
||||
.note("consider using the `async-trait` crate: \
|
||||
https://crates.io/crates/async-trait")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
|
7
src/test/ui/async-await/async-trait-fn.rs
Normal file
7
src/test/ui/async-await/async-trait-fn.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// edition:2018
|
||||
trait T {
|
||||
async fn foo() {} //~ ERROR trait fns cannot be declared `async`
|
||||
async fn bar(&self) {} //~ ERROR trait fns cannot be declared `async`
|
||||
}
|
||||
|
||||
fn main() {}
|
21
src/test/ui/async-await/async-trait-fn.stderr
Normal file
21
src/test/ui/async-await/async-trait-fn.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0706]: trait fns cannot be declared `async`
|
||||
--> $DIR/async-trait-fn.rs:3:5
|
||||
|
|
||||
LL | async fn foo() {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `async` trait functions are not currently supported
|
||||
= note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
|
||||
|
||||
error[E0706]: trait fns cannot be declared `async`
|
||||
--> $DIR/async-trait-fn.rs:4:5
|
||||
|
|
||||
LL | async fn bar(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `async` trait functions are not currently supported
|
||||
= note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0706`.
|
@ -57,7 +57,11 @@ error[E0706]: trait fns cannot be declared `async`
|
||||
|
|
||||
LL | async fn foo() {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `async` trait functions are not currently supported
|
||||
= note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0670`.
|
||||
Some errors have detailed explanations: E0670, E0706.
|
||||
For more information about an error, try `rustc --explain E0670`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user