Add separate 'async_closure' feature gate.
This commit is contained in:
parent
088b987307
commit
bb7fbb99a2
|
@ -31,6 +31,7 @@ use crate::tokenstream::TokenTree;
|
||||||
|
|
||||||
use errors::{Applicability, DiagnosticBuilder, Handler};
|
use errors::{Applicability, DiagnosticBuilder, Handler};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
use rustc_data_structures::sync::Lock;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
|
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
@ -573,6 +574,9 @@ declare_features! (
|
||||||
// Allows `impl Trait` with multiple unrelated lifetimes.
|
// Allows `impl Trait` with multiple unrelated lifetimes.
|
||||||
(active, member_constraints, "1.37.0", Some(61977), None),
|
(active, member_constraints, "1.37.0", Some(61977), None),
|
||||||
|
|
||||||
|
// Allows `async || body` closures.
|
||||||
|
(active, async_closure, "1.37.0", Some(62290), None),
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// feature-group-end: actual feature gates
|
// feature-group-end: actual feature gates
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
@ -2191,9 +2195,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||||
"labels on blocks are unstable");
|
"labels on blocks are unstable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Closure(_, ast::IsAsync::Async { .. }, ..) => {
|
|
||||||
gate_feature_post!(&self, async_await, e.span, "async closures are unstable");
|
|
||||||
}
|
|
||||||
ast::ExprKind::Async(..) => {
|
ast::ExprKind::Async(..) => {
|
||||||
gate_feature_post!(&self, async_await, e.span, "async blocks are unstable");
|
gate_feature_post!(&self, async_await, e.span, "async blocks are unstable");
|
||||||
}
|
}
|
||||||
|
@ -2527,6 +2528,10 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
|
||||||
features
|
features
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn for_each_in_lock<T>(vec: &Lock<Vec<T>>, f: impl Fn(&T)) {
|
||||||
|
vec.borrow().iter().for_each(f);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn check_crate(krate: &ast::Crate,
|
pub fn check_crate(krate: &ast::Crate,
|
||||||
sess: &ParseSess,
|
sess: &ParseSess,
|
||||||
features: &Features,
|
features: &Features,
|
||||||
|
@ -2539,28 +2544,27 @@ pub fn check_crate(krate: &ast::Crate,
|
||||||
plugin_attributes,
|
plugin_attributes,
|
||||||
};
|
};
|
||||||
|
|
||||||
sess
|
for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!(
|
||||||
.param_attr_spans
|
|
||||||
.borrow()
|
|
||||||
.iter()
|
|
||||||
.for_each(|span| gate_feature!(
|
|
||||||
&ctx,
|
&ctx,
|
||||||
param_attrs,
|
param_attrs,
|
||||||
*span,
|
*span,
|
||||||
"attributes on function parameters are unstable"
|
"attributes on function parameters are unstable"
|
||||||
));
|
));
|
||||||
|
|
||||||
sess
|
for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!(
|
||||||
.let_chains_spans
|
|
||||||
.borrow()
|
|
||||||
.iter()
|
|
||||||
.for_each(|span| gate_feature!(
|
|
||||||
&ctx,
|
&ctx,
|
||||||
let_chains,
|
let_chains,
|
||||||
*span,
|
*span,
|
||||||
"`let` expressions in this position are experimental"
|
"`let` expressions in this position are experimental"
|
||||||
));
|
));
|
||||||
|
|
||||||
|
for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!(
|
||||||
|
&ctx,
|
||||||
|
async_closure,
|
||||||
|
*span,
|
||||||
|
"async closures are unstable"
|
||||||
|
));
|
||||||
|
|
||||||
let visitor = &mut PostExpansionVisitor {
|
let visitor = &mut PostExpansionVisitor {
|
||||||
context: &ctx,
|
context: &ctx,
|
||||||
builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP,
|
builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP,
|
||||||
|
|
|
@ -1474,6 +1474,7 @@ mod tests {
|
||||||
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
||||||
param_attr_spans: Lock::new(Vec::new()),
|
param_attr_spans: Lock::new(Vec::new()),
|
||||||
let_chains_spans: Lock::new(Vec::new()),
|
let_chains_spans: Lock::new(Vec::new()),
|
||||||
|
async_closure_spans: Lock::new(Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,8 @@ pub struct ParseSess {
|
||||||
pub param_attr_spans: Lock<Vec<Span>>,
|
pub param_attr_spans: Lock<Vec<Span>>,
|
||||||
// Places where `let` exprs were used and should be feature gated according to `let_chains`.
|
// Places where `let` exprs were used and should be feature gated according to `let_chains`.
|
||||||
pub let_chains_spans: Lock<Vec<Span>>,
|
pub let_chains_spans: Lock<Vec<Span>>,
|
||||||
|
// Places where `async || ..` exprs were used and should be feature gated.
|
||||||
|
pub async_closure_spans: Lock<Vec<Span>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseSess {
|
impl ParseSess {
|
||||||
|
@ -84,6 +86,7 @@ impl ParseSess {
|
||||||
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
||||||
param_attr_spans: Lock::new(Vec::new()),
|
param_attr_spans: Lock::new(Vec::new()),
|
||||||
let_chains_spans: Lock::new(Vec::new()),
|
let_chains_spans: Lock::new(Vec::new()),
|
||||||
|
async_closure_spans: Lock::new(Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3221,21 +3221,24 @@ impl<'a> Parser<'a> {
|
||||||
-> PResult<'a, P<Expr>>
|
-> PResult<'a, P<Expr>>
|
||||||
{
|
{
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
|
|
||||||
let movability = if self.eat_keyword(kw::Static) {
|
let movability = if self.eat_keyword(kw::Static) {
|
||||||
Movability::Static
|
Movability::Static
|
||||||
} else {
|
} else {
|
||||||
Movability::Movable
|
Movability::Movable
|
||||||
};
|
};
|
||||||
|
|
||||||
let asyncness = if self.token.span.rust_2018() {
|
let asyncness = if self.token.span.rust_2018() {
|
||||||
self.parse_asyncness()
|
self.parse_asyncness()
|
||||||
} else {
|
} else {
|
||||||
IsAsync::NotAsync
|
IsAsync::NotAsync
|
||||||
};
|
};
|
||||||
let capture_clause = if self.eat_keyword(kw::Move) {
|
if asyncness.is_async() {
|
||||||
CaptureBy::Value
|
// Feature gate `async ||` closures.
|
||||||
} else {
|
self.sess.async_closure_spans.borrow_mut().push(self.prev_span);
|
||||||
CaptureBy::Ref
|
}
|
||||||
};
|
|
||||||
|
let capture_clause = self.parse_capture_clause();
|
||||||
let decl = self.parse_fn_block_decl()?;
|
let decl = self.parse_fn_block_decl()?;
|
||||||
let decl_hi = self.prev_span;
|
let decl_hi = self.prev_span;
|
||||||
let body = match decl.output {
|
let body = match decl.output {
|
||||||
|
@ -3257,7 +3260,7 @@ impl<'a> Parser<'a> {
|
||||||
attrs))
|
attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
// `else` token already eaten
|
/// `else` token already eaten
|
||||||
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
|
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
if self.eat_keyword(kw::If) {
|
if self.eat_keyword(kw::If) {
|
||||||
return self.parse_if_expr(ThinVec::new());
|
return self.parse_if_expr(ThinVec::new());
|
||||||
|
@ -3306,7 +3309,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs))
|
Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse `loop {...}`, `loop` token already eaten
|
/// Parse `loop {...}`, `loop` token already eaten.
|
||||||
fn parse_loop_expr(&mut self, opt_label: Option<Label>,
|
fn parse_loop_expr(&mut self, opt_label: Option<Label>,
|
||||||
span_lo: Span,
|
span_lo: Span,
|
||||||
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||||
|
@ -3316,17 +3319,20 @@ impl<'a> Parser<'a> {
|
||||||
Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs))
|
Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses an `async move {...}` expression.
|
/// Parse an optional `move` prefix to a closure lke construct.
|
||||||
pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>)
|
fn parse_capture_clause(&mut self) -> CaptureBy {
|
||||||
-> PResult<'a, P<Expr>>
|
if self.eat_keyword(kw::Move) {
|
||||||
{
|
|
||||||
let span_lo = self.token.span;
|
|
||||||
self.expect_keyword(kw::Async)?;
|
|
||||||
let capture_clause = if self.eat_keyword(kw::Move) {
|
|
||||||
CaptureBy::Value
|
CaptureBy::Value
|
||||||
} else {
|
} else {
|
||||||
CaptureBy::Ref
|
CaptureBy::Ref
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses an `async move? {...}` expression.
|
||||||
|
pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||||
|
let span_lo = self.token.span;
|
||||||
|
self.expect_keyword(kw::Async)?;
|
||||||
|
let capture_clause = self.parse_capture_clause();
|
||||||
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
||||||
attrs.extend(iattrs);
|
attrs.extend(iattrs);
|
||||||
Ok(self.mk_expr(
|
Ok(self.mk_expr(
|
||||||
|
|
|
@ -146,6 +146,7 @@ symbols! {
|
||||||
associated_type_defaults,
|
associated_type_defaults,
|
||||||
associated_types,
|
associated_types,
|
||||||
async_await,
|
async_await,
|
||||||
|
async_closure,
|
||||||
attr,
|
attr,
|
||||||
attributes,
|
attributes,
|
||||||
attr_literals,
|
attr_literals,
|
||||||
|
|
Loading…
Reference in New Issue