-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Add more context to async fn
trait error
#66526
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
aae7630
Add more context to `async fn` trait error. Suggest `async-trait`.
a767877
Reword help and add test
estebank e565329
Add error code documentation
estebank 846f5e6
Update E0706.md
Dylan-DPC a079159
Remove desugared `async-trait` example
estebank File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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: | ||
Dylan-DPC-zz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```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, | ||
Dylan-DPC-zz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 | ||
Dylan-DPC-zz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
this feature by sidesteping the language feature issue by desugaring to "boxed futures" | ||
Dylan-DPC-zz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(`Pin<Box<dyn Future + Send + 'async>>`): | ||
|
||
```edition2018,ignore (example-of-desugaring-equivalence) | ||
estebank marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#[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 hidden or 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 hidden or 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,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() {} |
This file contains hidden or 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,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`. |
This file contains hidden or 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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.