Skip to content

Commit fe95cd2

Browse files
committedNov 6, 2019
revamp pre-expansion gating infra
1 parent e8b190a commit fe95cd2

File tree

8 files changed

+65
-68
lines changed

8 files changed

+65
-68
lines changed
 

‎src/libsyntax/feature_gate/check.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -862,18 +862,17 @@ pub fn check_crate(krate: &ast::Crate,
862862
maybe_stage_features(&parse_sess.span_diagnostic, krate, unstable);
863863
let mut visitor = PostExpansionVisitor { parse_sess, features };
864864

865+
let spans = parse_sess.gated_spans.spans.borrow();
865866
macro_rules! gate_all {
866-
($gate:ident, $msg:literal) => { gate_all!($gate, $gate, $msg); };
867-
($spans:ident, $gate:ident, $msg:literal) => {
868-
for span in &*parse_sess.gated_spans.$spans.borrow() {
867+
($gate:ident, $msg:literal) => {
868+
for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
869869
gate_feature!(&visitor, $gate, *span, $msg);
870870
}
871871
}
872872
}
873-
874873
gate_all!(let_chains, "`let` expressions in this position are experimental");
875874
gate_all!(async_closure, "async closures are unstable");
876-
gate_all!(yields, generators, "yield syntax is experimental");
875+
gate_all!(generators, "yield syntax is experimental");
877876
gate_all!(or_patterns, "or-patterns syntax is experimental");
878877
gate_all!(const_extern_fn, "`const extern fn` definitions are unstable");
879878

@@ -901,7 +900,6 @@ pub fn check_crate(krate: &ast::Crate,
901900
gate_all!(try_blocks, "`try` blocks are unstable");
902901
gate_all!(label_break_value, "labels on blocks are unstable");
903902
gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead");
904-
905903
// To avoid noise about type ascription in common syntax errors,
906904
// only emit if it is the *only* error. (Also check it last.)
907905
if parse_sess.span_diagnostic.err_count() == 0 {

‎src/libsyntax/parse/parser.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,7 @@ impl<'a> Parser<'a> {
11211121
self.expected_tokens.push(TokenType::Keyword(kw::Crate));
11221122
if self.is_crate_vis() {
11231123
self.bump(); // `crate`
1124-
self.sess.gated_spans.crate_visibility_modifier.borrow_mut().push(self.prev_span);
1124+
self.sess.gated_spans.gate(sym::crate_visibility_modifier, self.prev_span);
11251125
return Ok(respan(self.prev_span, VisibilityKind::Crate(CrateSugar::JustCrate)));
11261126
}
11271127

‎src/libsyntax/parse/parser/expr.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ use crate::parse::token::{self, Token, TokenKind};
1616
use crate::print::pprust;
1717
use crate::ptr::P;
1818
use crate::source_map::{self, Span};
19-
use crate::symbol::{kw, sym};
2019
use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par};
2120

2221
use errors::Applicability;
22+
use syntax_pos::symbol::{kw, sym};
2323
use syntax_pos::Symbol;
2424
use std::mem;
2525
use rustc_data_structures::thin_vec::ThinVec;
@@ -252,7 +252,7 @@ impl<'a> Parser<'a> {
252252
self.last_type_ascription = Some((self.prev_span, maybe_path));
253253

254254
lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?;
255-
self.sess.gated_spans.type_ascription.borrow_mut().push(lhs.span);
255+
self.sess.gated_spans.gate(sym::type_ascription, lhs.span);
256256
continue
257257
} else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
258258
// If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to
@@ -455,7 +455,7 @@ impl<'a> Parser<'a> {
455455
let e = self.parse_prefix_expr(None);
456456
let (span, e) = self.interpolated_or_expr_span(e)?;
457457
let span = lo.to(span);
458-
self.sess.gated_spans.box_syntax.borrow_mut().push(span);
458+
self.sess.gated_spans.gate(sym::box_syntax, span);
459459
(span, ExprKind::Box(e))
460460
}
461461
token::Ident(..) if self.token.is_ident_named(sym::not) => {
@@ -1045,7 +1045,7 @@ impl<'a> Parser<'a> {
10451045
}
10461046

10471047
let span = lo.to(hi);
1048-
self.sess.gated_spans.yields.borrow_mut().push(span);
1048+
self.sess.gated_spans.gate(sym::generators, span);
10491049
} else if self.eat_keyword(kw::Let) {
10501050
return self.parse_let_expr(attrs);
10511051
} else if is_span_rust_2018 && self.eat_keyword(kw::Await) {
@@ -1264,7 +1264,7 @@ impl<'a> Parser<'a> {
12641264
outer_attrs: ThinVec<Attribute>,
12651265
) -> PResult<'a, P<Expr>> {
12661266
if let Some(label) = opt_label {
1267-
self.sess.gated_spans.label_break_value.borrow_mut().push(label.ident.span);
1267+
self.sess.gated_spans.gate(sym::label_break_value, label.ident.span);
12681268
}
12691269

12701270
self.expect(&token::OpenDelim(token::Brace))?;
@@ -1293,7 +1293,7 @@ impl<'a> Parser<'a> {
12931293
};
12941294
if asyncness.is_async() {
12951295
// Feature-gate `async ||` closures.
1296-
self.sess.gated_spans.async_closure.borrow_mut().push(self.prev_span);
1296+
self.sess.gated_spans.gate(sym::async_closure, self.prev_span);
12971297
}
12981298

12991299
let capture_clause = self.parse_capture_clause();
@@ -1415,8 +1415,7 @@ impl<'a> Parser<'a> {
14151415

14161416
if let ExprKind::Let(..) = cond.kind {
14171417
// Remove the last feature gating of a `let` expression since it's stable.
1418-
let last = self.sess.gated_spans.let_chains.borrow_mut().pop();
1419-
debug_assert_eq!(cond.span, last.unwrap());
1418+
self.sess.gated_spans.ungate_last(sym::let_chains, cond.span);
14201419
}
14211420

14221421
Ok(cond)
@@ -1433,7 +1432,7 @@ impl<'a> Parser<'a> {
14331432
|this| this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
14341433
)?;
14351434
let span = lo.to(expr.span);
1436-
self.sess.gated_spans.let_chains.borrow_mut().push(span);
1435+
self.sess.gated_spans.gate(sym::let_chains, span);
14371436
Ok(self.mk_expr(span, ExprKind::Let(pat, expr), attrs))
14381437
}
14391438

@@ -1654,7 +1653,7 @@ impl<'a> Parser<'a> {
16541653
Err(error)
16551654
} else {
16561655
let span = span_lo.to(body.span);
1657-
self.sess.gated_spans.try_blocks.borrow_mut().push(span);
1656+
self.sess.gated_spans.gate(sym::try_blocks, span);
16581657
Ok(self.mk_expr(span, ExprKind::TryBlock(body), attrs))
16591658
}
16601659
}

‎src/libsyntax/parse/parser/generics.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use super::{Parser, PResult};
33
use crate::ast::{self, WhereClause, GenericParam, GenericParamKind, GenericBounds, Attribute};
44
use crate::parse::token;
55
use crate::source_map::DUMMY_SP;
6-
use crate::symbol::kw;
6+
7+
use syntax_pos::symbol::{kw, sym};
78

89
impl<'a> Parser<'a> {
910
/// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
@@ -62,7 +63,7 @@ impl<'a> Parser<'a> {
6263
self.expect(&token::Colon)?;
6364
let ty = self.parse_ty()?;
6465

65-
self.sess.gated_spans.const_generics.borrow_mut().push(lo.to(self.prev_span));
66+
self.sess.gated_spans.gate(sym::const_generics, lo.to(self.prev_span));
6667

6768
Ok(GenericParam {
6869
ident,

‎src/libsyntax/parse/parser/item.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,7 @@ impl<'a> Parser<'a> {
147147
let unsafety = self.parse_unsafety();
148148

149149
if self.check_keyword(kw::Extern) {
150-
self.sess.gated_spans.const_extern_fn.borrow_mut().push(
151-
lo.to(self.token.span)
152-
);
150+
self.sess.gated_spans.gate(sym::const_extern_fn, lo.to(self.token.span));
153151
}
154152
let abi = self.parse_extern_abi()?;
155153
self.bump(); // `fn`
@@ -830,7 +828,7 @@ impl<'a> Parser<'a> {
830828
.emit();
831829
}
832830

833-
self.sess.gated_spans.trait_alias.borrow_mut().push(whole_span);
831+
self.sess.gated_spans.gate(sym::trait_alias, whole_span);
834832

835833
Ok((ident, ItemKind::TraitAlias(tps, bounds), None))
836834
} else {
@@ -1712,7 +1710,7 @@ impl<'a> Parser<'a> {
17121710
let span = lo.to(self.prev_span);
17131711

17141712
if !def.legacy {
1715-
self.sess.gated_spans.decl_macro.borrow_mut().push(span);
1713+
self.sess.gated_spans.gate(sym::decl_macro, span);
17161714
}
17171715

17181716
Ok(Some(self.mk_item(span, ident, ItemKind::MacroDef(def), vis.clone(), attrs.to_vec())))

‎src/libsyntax/parse/parser/pat.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ use crate::mut_visit::{noop_visit_pat, noop_visit_mac, MutVisitor};
88
use crate::parse::token::{self};
99
use crate::print::pprust;
1010
use crate::source_map::{respan, Span, Spanned};
11-
use crate::symbol::kw;
1211
use crate::ThinVec;
13-
12+
use syntax_pos::symbol::{kw, sym};
1413
use errors::{Applicability, DiagnosticBuilder};
1514

1615
type Expected = Option<&'static str>;
@@ -52,11 +51,8 @@ impl<'a> Parser<'a> {
5251
// and no other gated or-pattern has been parsed thus far,
5352
// then we should really gate the leading `|`.
5453
// This complicated procedure is done purely for diagnostics UX.
55-
if gated_leading_vert {
56-
let mut or_pattern_spans = self.sess.gated_spans.or_patterns.borrow_mut();
57-
if or_pattern_spans.is_empty() {
58-
or_pattern_spans.push(leading_vert_span);
59-
}
54+
if gated_leading_vert && self.sess.gated_spans.is_ungated(sym::or_patterns) {
55+
self.sess.gated_spans.gate(sym::or_patterns, leading_vert_span);
6056
}
6157

6258
Ok(pat)
@@ -117,7 +113,7 @@ impl<'a> Parser<'a> {
117113

118114
// Feature gate the or-pattern if instructed:
119115
if gate_or == GateOr::Yes {
120-
self.sess.gated_spans.or_patterns.borrow_mut().push(or_pattern_span);
116+
self.sess.gated_spans.gate(sym::or_patterns, or_pattern_span);
121117
}
122118

123119
Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats)))
@@ -325,7 +321,7 @@ impl<'a> Parser<'a> {
325321
} else if self.eat_keyword(kw::Box) {
326322
// Parse `box pat`
327323
let pat = self.parse_pat_with_range_pat(false, None)?;
328-
self.sess.gated_spans.box_patterns.borrow_mut().push(lo.to(self.prev_span));
324+
self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_span));
329325
PatKind::Box(pat)
330326
} else if self.can_be_ident_pat() {
331327
// Parse `ident @ pat`
@@ -612,7 +608,7 @@ impl<'a> Parser<'a> {
612608
}
613609

614610
fn excluded_range_end(&self, span: Span) -> RangeEnd {
615-
self.sess.gated_spans.exclusive_range_pattern.borrow_mut().push(span);
611+
self.sess.gated_spans.gate(sym::exclusive_range_pattern, span);
616612
RangeEnd::Excluded
617613
}
618614

‎src/libsyntax/parse/parser/path.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::ast::{self, QSelf, Path, PathSegment, Ident, ParenthesizedArgs, Angle
55
use crate::ast::{AnonConst, GenericArg, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
66
use crate::parse::token::{self, Token};
77
use crate::source_map::{Span, BytePos};
8-
use crate::symbol::kw;
8+
use syntax_pos::symbol::{kw, sym};
99

1010
use std::mem;
1111
use log::debug;
@@ -426,7 +426,7 @@ impl<'a> Parser<'a> {
426426

427427
// Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
428428
if let AssocTyConstraintKind::Bound { .. } = kind {
429-
self.sess.gated_spans.associated_type_bounds.borrow_mut().push(span);
429+
self.sess.gated_spans.gate(sym::associated_type_bounds, span);
430430
}
431431

432432
constraints.push(AssocTyConstraint {

‎src/libsyntax/sess.rs

+37-32
Original file line numberDiff line numberDiff line change
@@ -20,38 +20,43 @@ use std::str;
2020
/// used and should be feature gated accordingly in `check_crate`.
2121
#[derive(Default)]
2222
crate struct GatedSpans {
23-
/// Spans collected for gating `let_chains`, e.g. `if a && let b = c {}`.
24-
crate let_chains: Lock<Vec<Span>>,
25-
/// Spans collected for gating `async_closure`, e.g. `async || ..`.
26-
crate async_closure: Lock<Vec<Span>>,
27-
/// Spans collected for gating `yield e?` expressions (`generators` gate).
28-
crate yields: Lock<Vec<Span>>,
29-
/// Spans collected for gating `or_patterns`, e.g. `Some(Foo | Bar)`.
30-
crate or_patterns: Lock<Vec<Span>>,
31-
/// Spans collected for gating `const_extern_fn`, e.g. `const extern fn foo`.
32-
crate const_extern_fn: Lock<Vec<Span>>,
33-
/// Spans collected for gating `trait_alias`, e.g. `trait Foo = Ord + Eq;`.
34-
pub trait_alias: Lock<Vec<Span>>,
35-
/// Spans collected for gating `associated_type_bounds`, e.g. `Iterator<Item: Ord>`.
36-
pub associated_type_bounds: Lock<Vec<Span>>,
37-
/// Spans collected for gating `crate_visibility_modifier`, e.g. `crate fn`.
38-
pub crate_visibility_modifier: Lock<Vec<Span>>,
39-
/// Spans collected for gating `const_generics`, e.g. `const N: usize`.
40-
pub const_generics: Lock<Vec<Span>>,
41-
/// Spans collected for gating `decl_macro`, e.g. `macro m() {}`.
42-
pub decl_macro: Lock<Vec<Span>>,
43-
/// Spans collected for gating `box_patterns`, e.g. `box 0`.
44-
pub box_patterns: Lock<Vec<Span>>,
45-
/// Spans collected for gating `exclusive_range_pattern`, e.g. `0..2`.
46-
pub exclusive_range_pattern: Lock<Vec<Span>>,
47-
/// Spans collected for gating `try_blocks`, e.g. `try { a? + b? }`.
48-
pub try_blocks: Lock<Vec<Span>>,
49-
/// Spans collected for gating `label_break_value`, e.g. `'label: { ... }`.
50-
pub label_break_value: Lock<Vec<Span>>,
51-
/// Spans collected for gating `box_syntax`, e.g. `box $expr`.
52-
pub box_syntax: Lock<Vec<Span>>,
53-
/// Spans collected for gating `type_ascription`, e.g. `42: usize`.
54-
pub type_ascription: Lock<Vec<Span>>,
23+
crate spans: Lock<FxHashMap<Symbol, Vec<Span>>>,
24+
}
25+
26+
impl GatedSpans {
27+
/// Feature gate the given `span` under the given `feature`
28+
/// which is same `Symbol` used in `active.rs`.
29+
pub fn gate(&self, feature: Symbol, span: Span) {
30+
self.spans
31+
.borrow_mut()
32+
.entry(feature)
33+
.or_default()
34+
.push(span);
35+
}
36+
37+
/// Ungate the last span under the given `feature`.
38+
/// Panics if the given `span` wasn't the last one.
39+
///
40+
/// Using this is discouraged unless you have a really good reason to.
41+
pub fn ungate_last(&self, feature: Symbol, span: Span) {
42+
let removed_span = self.spans
43+
.borrow_mut()
44+
.entry(feature)
45+
.or_default()
46+
.pop()
47+
.unwrap();
48+
debug_assert_eq!(span, removed_span);
49+
}
50+
51+
/// Is the provided `feature` gate ungated currently?
52+
///
53+
/// Using this is discouraged unless you have a really good reason to.
54+
pub fn is_ungated(&self, feature: Symbol) -> bool {
55+
self.spans
56+
.borrow()
57+
.get(&feature)
58+
.map_or(true, |spans| spans.is_empty())
59+
}
5560
}
5661

5762
/// Info about a parsing session.

0 commit comments

Comments
 (0)
Please sign in to comment.