Skip to content

Commit 56e8f29

Browse files
committed
Auto merge of #51580 - cramertj:async-await, r=eddyb
async/await This PR implements `async`/`await` syntax for `async fn` in Rust 2015 and `async` closures and `async` blocks in Rust 2018 (tracking issue: #50547). Limitations: non-`move` async closures with arguments are currently not supported, nor are `async fn` with multiple different input lifetimes. These limitations are not fundamental and will be removed in the future, however I'd like to go ahead and get this PR merged so we can start experimenting with this in combination with futures 0.3. Based on #51414. cc @petrochenkov for parsing changes. r? @eddyb
2 parents 2ea922a + 30c17cc commit 56e8f29

File tree

69 files changed

+1796
-538
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1796
-538
lines changed

src/librustc/diagnostics.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -2131,5 +2131,10 @@ register_diagnostics! {
21312131
E0657, // `impl Trait` can only capture lifetimes bound at the fn level
21322132
E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
21332133
E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
2134-
E0697, // closures cannot be static
2134+
2135+
E0906, // closures cannot be static
2136+
2137+
E0725, // multiple different lifetimes used in arguments of `async fn`
2138+
E0726, // multiple elided lifetimes used in arguments of `async fn`
2139+
E0727, // `async` non-`move` closures with arguments are not currently supported
21352140
}

src/librustc/hir/intravisit.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
//! This order consistency is required in a few places in rustc, for
4242
//! example generator inference, and possibly also HIR borrowck.
4343
44-
use rustc_target::spec::abi::Abi;
4544
use syntax::ast::{NodeId, CRATE_NODE_ID, Ident, Name, Attribute};
4645
use syntax_pos::Span;
4746
use hir::*;
@@ -54,8 +53,8 @@ use std::u32;
5453

5554
#[derive(Copy, Clone, PartialEq, Eq)]
5655
pub enum FnKind<'a> {
57-
/// fn foo() or extern "Abi" fn foo()
58-
ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, &'a Visibility, &'a [Attribute]),
56+
/// #[xxx] pub async/const/extern "Abi" fn foo()
57+
ItemFn(Name, &'a Generics, FnHeader, &'a Visibility, &'a [Attribute]),
5958

6059
/// fn foo(&self)
6160
Method(Name, &'a MethodSig, Option<&'a Visibility>, &'a [Attribute]),
@@ -479,12 +478,10 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
479478
visitor.visit_ty(typ);
480479
visitor.visit_nested_body(body);
481480
}
482-
ItemFn(ref declaration, unsafety, constness, abi, ref generics, body_id) => {
481+
ItemFn(ref declaration, header, ref generics, body_id) => {
483482
visitor.visit_fn(FnKind::ItemFn(item.name,
484483
generics,
485-
unsafety,
486-
constness,
487-
abi,
484+
header,
488485
&item.vis,
489486
&item.attrs),
490487
declaration,

src/librustc/hir/lowering.rs

+562-172
Large diffs are not rendered by default.

src/librustc/hir/map/blocks.rs

+17-22
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ use hir as ast;
2525
use hir::map::{self, Node};
2626
use hir::{Expr, FnDecl};
2727
use hir::intravisit::FnKind;
28-
use rustc_target::spec::abi;
2928
use syntax::ast::{Attribute, Name, NodeId};
3029
use syntax_pos::Span;
3130

@@ -105,9 +104,7 @@ impl<'a> Code<'a> {
105104
struct ItemFnParts<'a> {
106105
name: Name,
107106
decl: &'a ast::FnDecl,
108-
unsafety: ast::Unsafety,
109-
constness: ast::Constness,
110-
abi: abi::Abi,
107+
header: ast::FnHeader,
111108
vis: &'a ast::Visibility,
112109
generics: &'a ast::Generics,
113110
body: ast::BodyId,
@@ -183,31 +180,31 @@ impl<'a> FnLikeNode<'a> {
183180

184181
pub fn constness(self) -> ast::Constness {
185182
match self.kind() {
186-
FnKind::ItemFn(_, _, _, constness, ..) => {
187-
constness
188-
}
189-
FnKind::Method(_, m, ..) => {
190-
m.constness
191-
}
183+
FnKind::ItemFn(_, _, header, ..) => header.constness,
184+
FnKind::Method(_, m, ..) => m.header.constness,
192185
_ => ast::Constness::NotConst
193186
}
194187
}
195188

189+
pub fn asyncness(self) -> ast::IsAsync {
190+
match self.kind() {
191+
FnKind::ItemFn(_, _, header, ..) => header.asyncness,
192+
FnKind::Method(_, m, ..) => m.header.asyncness,
193+
_ => ast::IsAsync::NotAsync
194+
}
195+
}
196+
196197
pub fn unsafety(self) -> ast::Unsafety {
197198
match self.kind() {
198-
FnKind::ItemFn(_, _, unsafety, ..) => {
199-
unsafety
200-
}
201-
FnKind::Method(_, m, ..) => {
202-
m.unsafety
203-
}
199+
FnKind::ItemFn(_, _, header, ..) => header.unsafety,
200+
FnKind::Method(_, m, ..) => m.header.unsafety,
204201
_ => ast::Unsafety::Normal
205202
}
206203
}
207204

208205
pub fn kind(self) -> FnKind<'a> {
209206
let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
210-
FnKind::ItemFn(p.name, p.generics, p.unsafety, p.constness, p.abi, p.vis, p.attrs)
207+
FnKind::ItemFn(p.name, p.generics, p.header, p.vis, p.attrs)
211208
};
212209
let closure = |c: ClosureParts<'a>| {
213210
FnKind::Closure(c.attrs)
@@ -232,19 +229,17 @@ impl<'a> FnLikeNode<'a> {
232229
{
233230
match self.node {
234231
map::NodeItem(i) => match i.node {
235-
ast::ItemFn(ref decl, unsafety, constness, abi, ref generics, block) =>
232+
ast::ItemFn(ref decl, header, ref generics, block) =>
236233
item_fn(ItemFnParts {
237234
id: i.id,
238235
name: i.name,
239236
decl: &decl,
240-
unsafety,
241237
body: block,
242-
generics,
243-
abi,
244238
vis: &i.vis,
245-
constness,
246239
span: i.span,
247240
attrs: &i.attrs,
241+
header,
242+
generics,
248243
}),
249244
_ => bug!("item FnLikeNode that is not fn-like"),
250245
},

src/librustc/hir/map/def_collector.rs

+62-4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,27 @@ impl<'a> DefCollector<'a> {
7373
self.parent_def = parent;
7474
}
7575

76+
fn visit_async_fn(
77+
&mut self,
78+
id: NodeId,
79+
async_node_id: NodeId,
80+
name: Name,
81+
span: Span,
82+
visit_fn: impl FnOnce(&mut DefCollector<'a>)
83+
) {
84+
// For async functions, we need to create their inner defs inside of a
85+
// closure to match their desugared representation.
86+
let fn_def_data = DefPathData::ValueNs(name.as_interned_str());
87+
let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span);
88+
return self.with_parent(fn_def, |this| {
89+
let closure_def = this.create_def(async_node_id,
90+
DefPathData::ClosureExpr,
91+
REGULAR_SPACE,
92+
span);
93+
this.with_parent(closure_def, visit_fn)
94+
})
95+
}
96+
7697
fn visit_macro_invoc(&mut self, id: NodeId) {
7798
if let Some(ref mut visit) = self.visit_macro_invoc {
7899
visit(MacroInvocationData {
@@ -99,6 +120,15 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
99120
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
100121
return visit::walk_item(self, i);
101122
}
123+
ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async(async_node_id), .. }, ..) => {
124+
return self.visit_async_fn(
125+
i.id,
126+
async_node_id,
127+
i.ident.name,
128+
i.span,
129+
|this| visit::walk_item(this, i)
130+
)
131+
}
102132
ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_interned_str()),
103133
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
104134
DefPathData::ValueNs(i.ident.name.as_interned_str()),
@@ -197,6 +227,17 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
197227

198228
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
199229
let def_data = match ii.node {
230+
ImplItemKind::Method(MethodSig {
231+
header: FnHeader { asyncness: IsAsync::Async(async_node_id), .. }, ..
232+
}, ..) => {
233+
return self.visit_async_fn(
234+
ii.id,
235+
async_node_id,
236+
ii.ident.name,
237+
ii.span,
238+
|this| visit::walk_impl_item(this, ii)
239+
)
240+
}
200241
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
201242
DefPathData::ValueNs(ii.ident.name.as_interned_str()),
202243
ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_interned_str()),
@@ -227,15 +268,32 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
227268

228269
match expr.node {
229270
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
230-
ExprKind::Closure(..) => {
231-
let def = self.create_def(expr.id,
271+
ExprKind::Closure(_, asyncness, ..) => {
272+
let closure_def = self.create_def(expr.id,
232273
DefPathData::ClosureExpr,
233274
REGULAR_SPACE,
234275
expr.span);
235-
self.parent_def = Some(def);
276+
self.parent_def = Some(closure_def);
277+
278+
// Async closures desugar to closures inside of closures, so
279+
// we must create two defs.
280+
if let IsAsync::Async(async_id) = asyncness {
281+
let async_def = self.create_def(async_id,
282+
DefPathData::ClosureExpr,
283+
REGULAR_SPACE,
284+
expr.span);
285+
self.parent_def = Some(async_def);
286+
}
287+
}
288+
ExprKind::Async(_, async_id, _) => {
289+
let async_def = self.create_def(async_id,
290+
DefPathData::ClosureExpr,
291+
REGULAR_SPACE,
292+
expr.span);
293+
self.parent_def = Some(async_def);
236294
}
237295
_ => {}
238-
}
296+
};
239297

240298
visit::walk_expr(self, expr);
241299
self.parent_def = parent_def;

src/librustc/hir/map/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ impl<'hir> MapEntry<'hir> {
174174
match self {
175175
EntryItem(_, _, ref item) => {
176176
match item.node {
177-
ItemFn(ref fn_decl, _, _, _, _, _) => Some(&fn_decl),
177+
ItemFn(ref fn_decl, _, _, _) => Some(&fn_decl),
178178
_ => None,
179179
}
180180
}
@@ -210,7 +210,7 @@ impl<'hir> MapEntry<'hir> {
210210
match item.node {
211211
ItemConst(_, body) |
212212
ItemStatic(.., body) |
213-
ItemFn(_, _, _, _, _, body) => Some(body),
213+
ItemFn(_, _, _, body) => Some(body),
214214
_ => None,
215215
}
216216
}

src/librustc/hir/mod.rs

+19-7
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ impl LifetimeName {
255255
}
256256
}
257257

258-
fn is_elided(&self) -> bool {
258+
pub fn is_elided(&self) -> bool {
259259
use self::LifetimeName::*;
260260
match self {
261261
Implicit | Underscore => true,
@@ -1506,9 +1506,7 @@ pub struct MutTy {
15061506
/// Represents a method's signature in a trait declaration or implementation.
15071507
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
15081508
pub struct MethodSig {
1509-
pub unsafety: Unsafety,
1510-
pub constness: Constness,
1511-
pub abi: Abi,
1509+
pub header: FnHeader,
15121510
pub decl: P<FnDecl>,
15131511
}
15141512

@@ -1736,7 +1734,13 @@ pub enum IsAuto {
17361734
No
17371735
}
17381736

1739-
#[derive(Copy, Clone, PartialEq, Eq,PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
1737+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
1738+
pub enum IsAsync {
1739+
Async,
1740+
NotAsync,
1741+
}
1742+
1743+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
17401744
pub enum Unsafety {
17411745
Unsafe,
17421746
Normal,
@@ -2012,6 +2016,14 @@ pub struct Item {
20122016
pub span: Span,
20132017
}
20142018

2019+
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
2020+
pub struct FnHeader {
2021+
pub unsafety: Unsafety,
2022+
pub constness: Constness,
2023+
pub asyncness: IsAsync,
2024+
pub abi: Abi,
2025+
}
2026+
20152027
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
20162028
pub enum Item_ {
20172029
/// An `extern crate` item, with optional *original* crate name if the crate was renamed.
@@ -2031,7 +2043,7 @@ pub enum Item_ {
20312043
/// A `const` item
20322044
ItemConst(P<Ty>, BodyId),
20332045
/// A function declaration
2034-
ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, BodyId),
2046+
ItemFn(P<FnDecl>, FnHeader, Generics, BodyId),
20352047
/// A module
20362048
ItemMod(Mod),
20372049
/// An external module
@@ -2096,7 +2108,7 @@ impl Item_ {
20962108

20972109
pub fn generics(&self) -> Option<&Generics> {
20982110
Some(match *self {
2099-
ItemFn(_, _, _, _, ref generics, _) |
2111+
ItemFn(_, _, ref generics, _) |
21002112
ItemTy(_, ref generics) |
21012113
ItemEnum(_, ref generics) |
21022114
ItemStruct(_, ref generics) |

0 commit comments

Comments
 (0)