From 42728642246154c3977cd58d378548dfffa881b3 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 14 Aug 2019 05:44:32 +0200 Subject: [PATCH 1/2] Feature gate 'yield ?' pre-expansion. --- src/libsyntax/feature_gate.rs | 12 ++++++----- src/libsyntax/parse/lexer/tests.rs | 1 + src/libsyntax/parse/mod.rs | 3 +++ src/libsyntax/parse/parser/expr.rs | 3 +++ .../feature-gates/feature-gate-generators.rs | 6 ++++++ .../feature-gate-generators.stderr | 20 ++++++++++++++++++- 6 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 08a113b53d032..d704c21c95884 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -2088,11 +2088,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "type ascription is experimental"); } } - ast::ExprKind::Yield(..) => { - gate_feature_post!(&self, generators, - e.span, - "yield syntax is experimental"); - } ast::ExprKind::TryBlock(_) => { gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); } @@ -2464,6 +2459,13 @@ pub fn check_crate(krate: &ast::Crate, "async closures are unstable" )); + for_each_in_lock(&sess.yield_spans, |span| gate_feature!( + &ctx, + generators, + *span, + "yield syntax is experimental" + )); + let visitor = &mut PostExpansionVisitor { context: &ctx, builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP, diff --git a/src/libsyntax/parse/lexer/tests.rs b/src/libsyntax/parse/lexer/tests.rs index fc47e4f0b185a..7f66d012356a3 100644 --- a/src/libsyntax/parse/lexer/tests.rs +++ b/src/libsyntax/parse/lexer/tests.rs @@ -34,6 +34,7 @@ fn mk_sess(sm: Lrc) -> ParseSess { param_attr_spans: Lock::new(Vec::new()), let_chains_spans: Lock::new(Vec::new()), async_closure_spans: Lock::new(Vec::new()), + yield_spans: Lock::new(Vec::new()), injected_crate_name: Once::new(), } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 80aa7a35266eb..31757130df18b 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -62,6 +62,8 @@ pub struct ParseSess { pub let_chains_spans: Lock>, // Places where `async || ..` exprs were used and should be feature gated. pub async_closure_spans: Lock>, + // Places where `yield e?` exprs were used and should be feature gated. + pub yield_spans: Lock>, pub injected_crate_name: Once, } @@ -91,6 +93,7 @@ impl ParseSess { param_attr_spans: Lock::new(Vec::new()), let_chains_spans: Lock::new(Vec::new()), async_closure_spans: Lock::new(Vec::new()), + yield_spans: Lock::new(Vec::new()), injected_crate_name: Once::new(), } } diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 4432c1329cbfe..3101acd5dcb09 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -993,6 +993,9 @@ impl<'a> Parser<'a> { } else { ex = ExprKind::Yield(None); } + + let span = lo.to(hi); + self.sess.yield_spans.borrow_mut().push(span); } else if self.eat_keyword(kw::Let) { return self.parse_let_expr(attrs); } else if is_span_rust_2018 && self.eat_keyword(kw::Await) { diff --git a/src/test/ui/feature-gates/feature-gate-generators.rs b/src/test/ui/feature-gates/feature-gate-generators.rs index cee930fd785b9..382d891feed84 100644 --- a/src/test/ui/feature-gates/feature-gate-generators.rs +++ b/src/test/ui/feature-gates/feature-gate-generators.rs @@ -2,3 +2,9 @@ fn main() { yield true; //~ ERROR yield syntax is experimental //~^ ERROR yield statement outside of generator literal } + +#[cfg(FALSE)] +fn foo() { + yield; //~ ERROR yield syntax is experimental + yield 0; //~ ERROR yield syntax is experimental +} diff --git a/src/test/ui/feature-gates/feature-gate-generators.stderr b/src/test/ui/feature-gates/feature-gate-generators.stderr index cdb056012542b..24b814b410c9d 100644 --- a/src/test/ui/feature-gates/feature-gate-generators.stderr +++ b/src/test/ui/feature-gates/feature-gate-generators.stderr @@ -7,12 +7,30 @@ LL | yield true; = note: for more information, see https://github.com/rust-lang/rust/issues/43122 = help: add `#![feature(generators)]` to the crate attributes to enable +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-generators.rs:8:5 + | +LL | yield; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/43122 + = help: add `#![feature(generators)]` to the crate attributes to enable + +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-generators.rs:9:5 + | +LL | yield 0; + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/43122 + = help: add `#![feature(generators)]` to the crate attributes to enable + error[E0627]: yield statement outside of generator literal --> $DIR/feature-gate-generators.rs:2:5 | LL | yield true; | ^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`. From 4fe201cc117a30c19e41affd32f699d094d87718 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 14 Aug 2019 06:09:11 +0200 Subject: [PATCH 2/2] Simplify pre-expansion gating in general. --- src/libsyntax/feature_gate.rs | 42 +++++++++-------------------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index d704c21c95884..d77baa9f8720e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -30,7 +30,6 @@ use crate::tokenstream::TokenTree; use errors::{Applicability, DiagnosticBuilder, Handler}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lock; use rustc_target::spec::abi::Abi; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use log::debug; @@ -2422,10 +2421,6 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], features } -fn for_each_in_lock(vec: &Lock>, f: impl Fn(&T)) { - vec.borrow().iter().for_each(f); -} - pub fn check_crate(krate: &ast::Crate, sess: &ParseSess, features: &Features, @@ -2438,33 +2433,16 @@ pub fn check_crate(krate: &ast::Crate, plugin_attributes, }; - for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!( - &ctx, - param_attrs, - *span, - "attributes on function parameters are unstable" - )); - - for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!( - &ctx, - let_chains, - *span, - "`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" - )); - - for_each_in_lock(&sess.yield_spans, |span| gate_feature!( - &ctx, - generators, - *span, - "yield syntax is experimental" - )); + macro_rules! gate_all { + ($spans:ident, $gate:ident, $msg:literal) => { + for span in &*sess.$spans.borrow() { gate_feature!(&ctx, $gate, *span, $msg); } + } + } + + gate_all!(param_attr_spans, param_attrs, "attributes on function parameters are unstable"); + gate_all!(let_chains_spans, let_chains, "`let` expressions in this position are experimental"); + gate_all!(async_closure_spans, async_closure, "async closures are unstable"); + gate_all!(yield_spans, generators, "yield syntax is experimental"); let visitor = &mut PostExpansionVisitor { context: &ctx,