Skip to content

Commit bb7fbb9

Browse files
committed
Add separate 'async_closure' feature gate.
1 parent 088b987 commit bb7fbb9

File tree

5 files changed

+54
-39
lines changed

5 files changed

+54
-39
lines changed

Diff for: src/libsyntax/feature_gate.rs

+28-24
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use crate::tokenstream::TokenTree;
3131

3232
use errors::{Applicability, DiagnosticBuilder, Handler};
3333
use rustc_data_structures::fx::FxHashMap;
34+
use rustc_data_structures::sync::Lock;
3435
use rustc_target::spec::abi::Abi;
3536
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
3637
use log::debug;
@@ -573,6 +574,9 @@ declare_features! (
573574
// Allows `impl Trait` with multiple unrelated lifetimes.
574575
(active, member_constraints, "1.37.0", Some(61977), None),
575576

577+
// Allows `async || body` closures.
578+
(active, async_closure, "1.37.0", Some(62290), None),
579+
576580
// -------------------------------------------------------------------------
577581
// feature-group-end: actual feature gates
578582
// -------------------------------------------------------------------------
@@ -2191,9 +2195,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
21912195
"labels on blocks are unstable");
21922196
}
21932197
}
2194-
ast::ExprKind::Closure(_, ast::IsAsync::Async { .. }, ..) => {
2195-
gate_feature_post!(&self, async_await, e.span, "async closures are unstable");
2196-
}
21972198
ast::ExprKind::Async(..) => {
21982199
gate_feature_post!(&self, async_await, e.span, "async blocks are unstable");
21992200
}
@@ -2527,6 +2528,10 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
25272528
features
25282529
}
25292530

2531+
fn for_each_in_lock<T>(vec: &Lock<Vec<T>>, f: impl Fn(&T)) {
2532+
vec.borrow().iter().for_each(f);
2533+
}
2534+
25302535
pub fn check_crate(krate: &ast::Crate,
25312536
sess: &ParseSess,
25322537
features: &Features,
@@ -2539,27 +2544,26 @@ pub fn check_crate(krate: &ast::Crate,
25392544
plugin_attributes,
25402545
};
25412546

2542-
sess
2543-
.param_attr_spans
2544-
.borrow()
2545-
.iter()
2546-
.for_each(|span| gate_feature!(
2547-
&ctx,
2548-
param_attrs,
2549-
*span,
2550-
"attributes on function parameters are unstable"
2551-
));
2552-
2553-
sess
2554-
.let_chains_spans
2555-
.borrow()
2556-
.iter()
2557-
.for_each(|span| gate_feature!(
2558-
&ctx,
2559-
let_chains,
2560-
*span,
2561-
"`let` expressions in this position are experimental"
2562-
));
2547+
for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!(
2548+
&ctx,
2549+
param_attrs,
2550+
*span,
2551+
"attributes on function parameters are unstable"
2552+
));
2553+
2554+
for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!(
2555+
&ctx,
2556+
let_chains,
2557+
*span,
2558+
"`let` expressions in this position are experimental"
2559+
));
2560+
2561+
for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!(
2562+
&ctx,
2563+
async_closure,
2564+
*span,
2565+
"async closures are unstable"
2566+
));
25632567

25642568
let visitor = &mut PostExpansionVisitor {
25652569
context: &ctx,

Diff for: src/libsyntax/parse/lexer/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1474,6 +1474,7 @@ mod tests {
14741474
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
14751475
param_attr_spans: Lock::new(Vec::new()),
14761476
let_chains_spans: Lock::new(Vec::new()),
1477+
async_closure_spans: Lock::new(Vec::new()),
14771478
}
14781479
}
14791480

Diff for: src/libsyntax/parse/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ pub struct ParseSess {
5757
pub param_attr_spans: Lock<Vec<Span>>,
5858
// Places where `let` exprs were used and should be feature gated according to `let_chains`.
5959
pub let_chains_spans: Lock<Vec<Span>>,
60+
// Places where `async || ..` exprs were used and should be feature gated.
61+
pub async_closure_spans: Lock<Vec<Span>>,
6062
}
6163

6264
impl ParseSess {
@@ -84,6 +86,7 @@ impl ParseSess {
8486
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
8587
param_attr_spans: Lock::new(Vec::new()),
8688
let_chains_spans: Lock::new(Vec::new()),
89+
async_closure_spans: Lock::new(Vec::new()),
8790
}
8891
}
8992

Diff for: src/libsyntax/parse/parser.rs

+21-15
Original file line numberDiff line numberDiff line change
@@ -3221,21 +3221,24 @@ impl<'a> Parser<'a> {
32213221
-> PResult<'a, P<Expr>>
32223222
{
32233223
let lo = self.token.span;
3224+
32243225
let movability = if self.eat_keyword(kw::Static) {
32253226
Movability::Static
32263227
} else {
32273228
Movability::Movable
32283229
};
3230+
32293231
let asyncness = if self.token.span.rust_2018() {
32303232
self.parse_asyncness()
32313233
} else {
32323234
IsAsync::NotAsync
32333235
};
3234-
let capture_clause = if self.eat_keyword(kw::Move) {
3235-
CaptureBy::Value
3236-
} else {
3237-
CaptureBy::Ref
3238-
};
3236+
if asyncness.is_async() {
3237+
// Feature gate `async ||` closures.
3238+
self.sess.async_closure_spans.borrow_mut().push(self.prev_span);
3239+
}
3240+
3241+
let capture_clause = self.parse_capture_clause();
32393242
let decl = self.parse_fn_block_decl()?;
32403243
let decl_hi = self.prev_span;
32413244
let body = match decl.output {
@@ -3257,7 +3260,7 @@ impl<'a> Parser<'a> {
32573260
attrs))
32583261
}
32593262

3260-
// `else` token already eaten
3263+
/// `else` token already eaten
32613264
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
32623265
if self.eat_keyword(kw::If) {
32633266
return self.parse_if_expr(ThinVec::new());
@@ -3306,7 +3309,7 @@ impl<'a> Parser<'a> {
33063309
Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs))
33073310
}
33083311

3309-
// parse `loop {...}`, `loop` token already eaten
3312+
/// Parse `loop {...}`, `loop` token already eaten.
33103313
fn parse_loop_expr(&mut self, opt_label: Option<Label>,
33113314
span_lo: Span,
33123315
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
@@ -3316,17 +3319,20 @@ impl<'a> Parser<'a> {
33163319
Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs))
33173320
}
33183321

3319-
/// Parses an `async move {...}` expression.
3320-
pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>)
3321-
-> PResult<'a, P<Expr>>
3322-
{
3323-
let span_lo = self.token.span;
3324-
self.expect_keyword(kw::Async)?;
3325-
let capture_clause = if self.eat_keyword(kw::Move) {
3322+
/// Parse an optional `move` prefix to a closure lke construct.
3323+
fn parse_capture_clause(&mut self) -> CaptureBy {
3324+
if self.eat_keyword(kw::Move) {
33263325
CaptureBy::Value
33273326
} else {
33283327
CaptureBy::Ref
3329-
};
3328+
}
3329+
}
3330+
3331+
/// Parses an `async move? {...}` expression.
3332+
pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
3333+
let span_lo = self.token.span;
3334+
self.expect_keyword(kw::Async)?;
3335+
let capture_clause = self.parse_capture_clause();
33303336
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
33313337
attrs.extend(iattrs);
33323338
Ok(self.mk_expr(

Diff for: src/libsyntax_pos/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ symbols! {
146146
associated_type_defaults,
147147
associated_types,
148148
async_await,
149+
async_closure,
149150
attr,
150151
attributes,
151152
attr_literals,

0 commit comments

Comments
 (0)