Skip to content

Commit

Permalink
Rollup merge of #63209 - Centril:stabilize-async-await, r=cramertj
Browse files Browse the repository at this point in the history
Stabilize `async_await` in Rust 1.39.0

Here we stabilize:
- free and inherent `async fn`s,
- the `<expr>.await` expression form,
- and the `async move? { ... }` block form.

Closes #62149.
Closes #50547.

All the blockers are now closed.

<details>
- [x] FCP in #62149
- [x] #61949; PR in #62849.
- [x] #62517; PR in #63376.
- [x] #63225; PR in #63501
- [x] #63388; PR in #63499
- [x] #63500; PR in #63501
- [x] #62121 (comment)
    - [x] Some tests for control flow (PR #63387):
          - `?`
          - `return` in `async` blocks
          - `break`
    - [x] #61775 (comment), i.e. tests for #60944 with `async fn`s instead). PR in #63383

</details>

r? @cramertj
  • Loading branch information
Centril committed Aug 20, 2019
2 parents 4593f40 + 21476e7 commit 3f7e7c2
Show file tree
Hide file tree
Showing 181 changed files with 271 additions and 605 deletions.
2 changes: 0 additions & 2 deletions src/librustc/error_codes.rs
Expand Up @@ -2088,7 +2088,6 @@ generator can be constructed.
Erroneous code example:
```edition2018,compile-fail,E0698
#![feature(async_await)]
async fn bar<T>() -> () {}
async fn foo() {
Expand All @@ -2101,7 +2100,6 @@ To fix this you must bind `T` to a concrete type such as `String`
so that a generator can then be constructed:
```edition2018
#![feature(async_await)]
async fn bar<T>() -> () {}
async fn foo() {
Expand Down
2 changes: 0 additions & 2 deletions src/librustc_typeck/check/mod.rs
Expand Up @@ -4197,8 +4197,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// A possible error is to forget to add `.await` when using futures:
///
/// ```
/// #![feature(async_await)]
///
/// async fn make_u32() -> u32 {
/// 22
/// }
Expand Down
7 changes: 2 additions & 5 deletions src/librustc_typeck/error_codes.rs
Expand Up @@ -4751,7 +4751,6 @@ E0733: r##"
Recursion in an `async fn` requires boxing. For example, this will not compile:
```edition2018,compile_fail,E0733
#![feature(async_await)]
async fn foo(n: usize) {
if n > 0 {
foo(n - 1).await;
Expand All @@ -4763,12 +4762,11 @@ To achieve async recursion, the `async fn` needs to be desugared
such that the `Future` is explicit in the return type:
```edition2018,compile_fail,E0720
# #![feature(async_await)]
use std::future::Future;
fn foo_desugered(n: usize) -> impl Future<Output = ()> {
fn foo_desugared(n: usize) -> impl Future<Output = ()> {
async move {
if n > 0 {
foo_desugered(n - 1).await;
foo_desugared(n - 1).await;
}
}
}
Expand All @@ -4777,7 +4775,6 @@ fn foo_desugered(n: usize) -> impl Future<Output = ()> {
Finally, the future is wrapped in a pinned box:
```edition2018
# #![feature(async_await)]
use std::future::Future;
use std::pin::Pin;
fn foo_recursive(n: usize) -> Pin<Box<dyn Future<Output = ()>>> {
Expand Down
2 changes: 0 additions & 2 deletions src/libstd/keyword_docs.rs
Expand Up @@ -984,7 +984,6 @@ mod where_keyword { }

// 2018 Edition keywords

#[unstable(feature = "async_await", issue = "50547")]
#[doc(keyword = "async")]
//
/// Return a [`Future`] instead of blocking the current thread.
Expand All @@ -995,7 +994,6 @@ mod where_keyword { }
/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
mod async_keyword { }

#[unstable(feature = "async_await", issue = "50547")]
#[doc(keyword = "await")]
//
/// Suspend execution until the result of a [`Future`] is ready.
Expand Down
19 changes: 2 additions & 17 deletions src/libsyntax/feature_gate.rs
Expand Up @@ -461,9 +461,6 @@ declare_features! (
// Allows using `#[doc(keyword = "...")]`.
(active, doc_keyword, "1.28.0", Some(51315), None),

// Allows async and await syntax.
(active, async_await, "1.28.0", Some(50547), None),

// Allows reinterpretation of the bits of a value of one type as another type during const eval.
(active, const_transmute, "1.29.0", Some(53605), None),

Expand Down Expand Up @@ -857,6 +854,8 @@ declare_features! (
(accepted, repr_align_enum, "1.37.0", Some(57996), None),
// Allows `const _: TYPE = VALUE`.
(accepted, underscore_const_names, "1.37.0", Some(54912), None),
// Allows free and inherent `async fn`s, `async` blocks, and `<expr>.await` expressions.
(accepted, async_await, "1.38.0", Some(50547), None),

// -------------------------------------------------------------------------
// feature-group-end: accepted features
Expand Down Expand Up @@ -2100,12 +2099,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
"labels on blocks are unstable");
}
}
ast::ExprKind::Async(..) => {
gate_feature_post!(&self, async_await, e.span, "async blocks are unstable");
}
ast::ExprKind::Await(_) => {
gate_feature_post!(&self, async_await, e.span, "async/await is unstable");
}
_ => {}
}
visit::walk_expr(self, e)
Expand Down Expand Up @@ -2154,11 +2147,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
span: Span,
_node_id: NodeId) {
if let Some(header) = fn_kind.header() {
// Check for const fn and async fn declarations.
if header.asyncness.node.is_async() {
gate_feature_post!(&self, async_await, span, "async fn is unstable");
}

// Stability of const fn methods are covered in
// `visit_trait_item` and `visit_impl_item` below; this is
// because default methods don't pass through this point.
Expand Down Expand Up @@ -2198,9 +2186,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
if block.is_none() {
self.check_abi(sig.header.abi, ti.span);
}
if sig.header.asyncness.node.is_async() {
gate_feature_post!(&self, async_await, ti.span, "async fn is unstable");
}
if sig.decl.c_variadic {
gate_feature_post!(&self, c_variadic, ti.span,
"C-variadic functions are unstable");
Expand Down
2 changes: 0 additions & 2 deletions src/test/rustdoc/async-fn.rs
@@ -1,7 +1,5 @@
// edition:2018

#![feature(async_await)]

// @has async_fn/fn.foo.html '//pre[@class="rust fn"]' 'pub async fn foo() -> Option<Foo>'
pub async fn foo() -> Option<Foo> {
None
Expand Down
6 changes: 2 additions & 4 deletions src/test/rustdoc/async-move-doctest.rs
@@ -1,13 +1,11 @@
// compile-flags:--test
// edition:2018

// prior to setting the default edition for the doctest pre-parser, this doctest would fail due to
// a fatal parsing error
// Prior to setting the default edition for the doctest pre-parser,
// this doctest would fail due to a fatal parsing error.
// see https://github.com/rust-lang/rust/issues/59313

//! ```
//! #![feature(async_await)]
//!
//! fn foo() {
//! drop(async move {});
//! }
Expand Down
3 changes: 0 additions & 3 deletions src/test/rustdoc/edition-flag.rs
@@ -1,10 +1,7 @@
// compile-flags:--test -Z unstable-options
// edition:2018

#![feature(async_await)]

/// ```rust
/// #![feature(async_await)]
/// fn main() {
/// let _ = async { };
/// }
Expand Down
1 change: 0 additions & 1 deletion src/test/ui/async-await/argument-patterns.rs
Expand Up @@ -3,7 +3,6 @@

#![allow(unused_variables)]
#![deny(unused_mut)]
#![feature(async_await)]

type A = Vec<u32>;

Expand Down
2 changes: 0 additions & 2 deletions src/test/ui/async-await/async-await.rs
Expand Up @@ -3,8 +3,6 @@
// edition:2018
// aux-build:arc_wake.rs

#![feature(async_await)]

extern crate arc_wake;

use std::pin::Pin;
Expand Down
Expand Up @@ -6,8 +6,6 @@
// edition:2018
// ignore-tidy-linelength

#![feature(async_await)]

fn main() {}

use core::future::Future;
Expand Down
@@ -1,17 +1,17 @@
error[E0267]: `break` inside of an async block
--> $DIR/async-block-control-flow-static-semantics.rs:35:9
--> $DIR/async-block-control-flow-static-semantics.rs:33:9
|
LL | break 0u8;
| ^^^^^^^^^ cannot break inside of an async block

error[E0267]: `break` inside of an async block
--> $DIR/async-block-control-flow-static-semantics.rs:42:13
--> $DIR/async-block-control-flow-static-semantics.rs:40:13
|
LL | break 0u8;
| ^^^^^^^^^ cannot break inside of an async block

error[E0308]: mismatched types
--> $DIR/async-block-control-flow-static-semantics.rs:15:43
--> $DIR/async-block-control-flow-static-semantics.rs:13:43
|
LL | fn return_targets_async_block_not_fn() -> u8 {
| --------------------------------- ^^ expected u8, found ()
Expand All @@ -22,7 +22,7 @@ LL | fn return_targets_async_block_not_fn() -> u8 {
found type `()`

error[E0271]: type mismatch resolving `<impl std::future::Future as std::future::Future>::Output == ()`
--> $DIR/async-block-control-flow-static-semantics.rs:20:39
--> $DIR/async-block-control-flow-static-semantics.rs:18:39
|
LL | let _: &dyn Future<Output = ()> = &block;
| ^^^^^^ expected u8, found ()
Expand All @@ -32,7 +32,7 @@ LL | let _: &dyn Future<Output = ()> = &block;
= note: required for the cast to the object type `dyn std::future::Future<Output = ()>`

error[E0271]: type mismatch resolving `<impl std::future::Future as std::future::Future>::Output == ()`
--> $DIR/async-block-control-flow-static-semantics.rs:29:39
--> $DIR/async-block-control-flow-static-semantics.rs:27:39
|
LL | let _: &dyn Future<Output = ()> = &block;
| ^^^^^^ expected u8, found ()
Expand All @@ -42,7 +42,7 @@ LL | let _: &dyn Future<Output = ()> = &block;
= note: required for the cast to the object type `dyn std::future::Future<Output = ()>`

error[E0271]: type mismatch resolving `<impl std::future::Future as std::future::Future>::Output == u8`
--> $DIR/async-block-control-flow-static-semantics.rs:24:55
--> $DIR/async-block-control-flow-static-semantics.rs:22:55
|
LL | async fn return_targets_async_block_not_async_fn() -> u8 {
| ^^ expected (), found u8
Expand All @@ -52,7 +52,7 @@ LL | async fn return_targets_async_block_not_async_fn() -> u8 {
= note: the return type of a function must have a statically known size

error[E0308]: mismatched types
--> $DIR/async-block-control-flow-static-semantics.rs:50:44
--> $DIR/async-block-control-flow-static-semantics.rs:48:44
|
LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
| ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
Expand All @@ -63,7 +63,7 @@ LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
found type `()`

error[E0308]: mismatched types
--> $DIR/async-block-control-flow-static-semantics.rs:59:50
--> $DIR/async-block-control-flow-static-semantics.rs:57:50
|
LL | fn rethrow_targets_async_block_not_async_fn() -> Result<u8, MyErr> {
| ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found ()
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/async-await/async-closure-matches-expr.rs
@@ -1,7 +1,7 @@
// build-pass
// edition:2018

#![feature(async_await, async_closure)]
#![feature(async_closure)]

macro_rules! match_expr {
($x:expr) => {}
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/async-await/async-closure.rs
Expand Up @@ -3,7 +3,7 @@
// edition:2018
// aux-build:arc_wake.rs

#![feature(async_await, async_closure)]
#![feature(async_closure)]

extern crate arc_wake;

Expand Down
3 changes: 1 addition & 2 deletions src/test/ui/async-await/async-error-span.rs
@@ -1,7 +1,6 @@
// edition:2018
#![feature(async_await)]

// Regression test for issue #62382
// Regression test for issue #62382.

use std::future::Future;

Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/async-await/async-error-span.stderr
@@ -1,11 +1,11 @@
error[E0698]: type inside `async` object must be known in this context
--> $DIR/async-error-span.rs:13:9
--> $DIR/async-error-span.rs:12:9
|
LL | let a;
| ^ cannot infer type
|
note: the type is part of the `async` object because of this `await`
--> $DIR/async-error-span.rs:14:5
--> $DIR/async-error-span.rs:13:5
|
LL | get_future().await;
| ^^^^^^^^^^^^^^^^^^
Expand Down
Expand Up @@ -6,8 +6,6 @@
// check-pass
// edition:2018

#![feature(async_await)]

struct Foo<'a>(&'a u8);

impl Foo<'_> {
Expand Down
2 changes: 0 additions & 2 deletions src/test/ui/async-await/async-fn-nonsend.rs
Expand Up @@ -2,8 +2,6 @@
// edition:2018
// compile-flags: --crate-type lib

#![feature(async_await)]

use std::{
cell::RefCell,
fmt::Debug,
Expand Down

0 comments on commit 3f7e7c2

Please sign in to comment.