diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-10-25 06:18:09 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-10-25 06:18:09 +0200 |
| commit | d6a18b6baf40b48abce2de5747d187a7bbad293d (patch) | |
| tree | c633afa2e2d4a69ce731623362fad60a23e526bb /src/libsyntax | |
| parent | fb602c7e4f5f01203c63e9c6939efa8c8f7c962a (diff) | |
| parent | 15a6c09b6e8a977f2c6f5a73de01a20d00b37930 (diff) | |
| download | rust-d6a18b6baf40b48abce2de5747d187a7bbad293d.tar.gz rust-d6a18b6baf40b48abce2de5747d187a7bbad293d.zip | |
Rollup merge of #65742 - Centril:gate-pre-expansion-subset, r=davidtwco
Pre-expansion gate most of the things This is a subset of https://github.com/rust-lang/rust/pull/64672. A crater run has already been done and this PR implements conclusions according to https://github.com/rust-lang/rust/pull/64672#issuecomment-542703363. r? @davidtwco cc @petrochenkov
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/feature_gate/check.rs | 150 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser/expr.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser/generics.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser/item.rs | 35 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser/pat.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser/path.rs | 12 | ||||
| -rw-r--r-- | src/libsyntax/sess.rs | 22 |
8 files changed, 124 insertions, 126 deletions
diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 172511f0f09..502b1c0f743 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -3,12 +3,8 @@ use super::accepted::ACCEPTED_FEATURES; use super::removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES}; use super::builtin_attrs::{AttributeGate, BUILTIN_ATTRIBUTE_MAP}; -use crate::ast::{ - self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind, - PatKind, RangeEnd, VariantData, -}; +use crate::ast::{self, NodeId, PatKind, VariantData}; use crate::attr::{self, check_builtin_attribute}; -use crate::source_map::Spanned; use crate::edition::{ALL_EDITIONS, Edition}; use crate::visit::{self, FnKind, Visitor}; use crate::parse::token; @@ -157,9 +153,6 @@ fn leveled_feature_err<'a, S: Into<MultiSpan>>( } -const EXPLAIN_BOX_SYNTAX: &str = - "box expression syntax is experimental; you can call `Box::new` instead"; - pub const EXPLAIN_STMT_ATTR_SYNTAX: &str = "attributes on expressions are experimental"; @@ -291,6 +284,25 @@ impl<'a> PostExpansionVisitor<'a> { err.emit(); } } + + fn check_gat(&self, generics: &ast::Generics, span: Span) { + if !generics.params.is_empty() { + gate_feature_post!( + &self, + generic_associated_types, + span, + "generic associated types are unstable" + ); + } + if !generics.where_clause.predicates.is_empty() { + gate_feature_post!( + &self, + generic_associated_types, + span, + "where clauses on associated types are unstable" + ); + } + } } impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { @@ -423,20 +435,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "auto traits are experimental and possibly buggy"); } - ast::ItemKind::TraitAlias(..) => { - gate_feature_post!( - &self, - trait_alias, - i.span, - "trait aliases are experimental" - ); - } - - ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => { - let msg = "`macro` is experimental"; - gate_feature_post!(&self, decl_macro, i.span, msg); - } - ast::ItemKind::OpaqueTy(..) => { gate_feature_post!( &self, @@ -500,37 +498,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - fn visit_expr(&mut self, e: &'a ast::Expr) { - match e.kind { - ast::ExprKind::Box(_) => { - gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX); - } - ast::ExprKind::Type(..) => { - // To avoid noise about type ascription in common syntax errors, only emit if it - // is the *only* error. - if self.parse_sess.span_diagnostic.err_count() == 0 { - gate_feature_post!(&self, type_ascription, e.span, - "type ascription is experimental"); - } - } - ast::ExprKind::TryBlock(_) => { - gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); - } - ast::ExprKind::Block(_, opt_label) => { - if let Some(label) = opt_label { - gate_feature_post!(&self, label_break_value, label.ident.span, - "labels on blocks are unstable"); - } - } - _ => {} - } - visit::walk_expr(self, e) - } - - fn visit_arm(&mut self, arm: &'a ast::Arm) { - visit::walk_arm(self, arm) - } - fn visit_pat(&mut self, pattern: &'a ast::Pat) { match &pattern.kind { PatKind::Slice(pats) => { @@ -550,25 +517,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } } - PatKind::Box(..) => { - gate_feature_post!(&self, box_patterns, - pattern.span, - "box pattern syntax is experimental"); - } - PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => { - gate_feature_post!(&self, exclusive_range_pattern, pattern.span, - "exclusive range pattern syntax is experimental"); - } _ => {} } visit::walk_pat(self, pattern) } - fn visit_fn(&mut self, - fn_kind: FnKind<'a>, - fn_decl: &'a ast::FnDecl, - span: Span, - _node_id: NodeId) { + fn visit_fn(&mut self, fn_kind: FnKind<'a>, fn_decl: &'a ast::FnDecl, span: Span, _: NodeId) { if let Some(header) = fn_kind.header() { // Stability of const fn methods are covered in // `visit_trait_item` and `visit_impl_item` below; this is @@ -583,26 +537,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_fn(self, fn_kind, fn_decl, span) } - fn visit_generic_param(&mut self, param: &'a GenericParam) { - match param.kind { - GenericParamKind::Const { .. } => - gate_feature_post!(&self, const_generics, param.ident.span, - "const generics are unstable"), - _ => {} - } - visit::walk_generic_param(self, param) - } - - fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) { - match constraint.kind { - AssocTyConstraintKind::Bound { .. } => - gate_feature_post!(&self, associated_type_bounds, constraint.span, - "associated type bounds are unstable"), - _ => {} - } - visit::walk_assoc_ty_constraint(self, constraint) - } - fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) { match ti.kind { ast::TraitItemKind::Method(ref sig, ref block) => { @@ -624,14 +558,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, associated_type_defaults, ti.span, "associated type defaults are unstable"); } - if !ti.generics.params.is_empty() { - gate_feature_post!(&self, generic_associated_types, ti.span, - "generic associated types are unstable"); - } - if !ti.generics.where_clause.predicates.is_empty() { - gate_feature_post!(&self, generic_associated_types, ti.span, - "where clauses on associated types are unstable"); - } + self.check_gat(&ti.generics, ti.span); } _ => {} } @@ -661,27 +588,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ); } ast::ImplItemKind::TyAlias(_) => { - if !ii.generics.params.is_empty() { - gate_feature_post!(&self, generic_associated_types, ii.span, - "generic associated types are unstable"); - } - if !ii.generics.where_clause.predicates.is_empty() { - gate_feature_post!(&self, generic_associated_types, ii.span, - "where clauses on associated types are unstable"); - } + self.check_gat(&ii.generics, ii.span); } _ => {} } visit::walk_impl_item(self, ii) } - - fn visit_vis(&mut self, vis: &'a ast::Visibility) { - if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node { - gate_feature_post!(&self, crate_visibility_modifier, vis.span, - "`crate` visibility modifier is experimental"); - } - visit::walk_vis(self, vis) - } } pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], @@ -867,6 +779,22 @@ pub fn check_crate(krate: &ast::Crate, gate_all!(yields, generators, "yield syntax is experimental"); gate_all!(or_patterns, "or-patterns syntax is experimental"); gate_all!(const_extern_fn, "`const extern fn` definitions are unstable"); + gate_all!(trait_alias, "trait aliases are experimental"); + gate_all!(associated_type_bounds, "associated type bounds are unstable"); + gate_all!(crate_visibility_modifier, "`crate` visibility modifier is experimental"); + gate_all!(const_generics, "const generics are unstable"); + gate_all!(decl_macro, "`macro` is experimental"); + gate_all!(box_patterns, "box pattern syntax is experimental"); + gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental"); + gate_all!(try_blocks, "`try` blocks are unstable"); + gate_all!(label_break_value, "labels on blocks are unstable"); + gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead"); + + // To avoid noise about type ascription in common syntax errors, + // only emit if it is the *only* error. (Also check it last.) + if parse_sess.span_diagnostic.err_count() == 0 { + gate_all!(type_ascription, "type ascription is experimental"); + } visit::walk_crate(&mut visitor, krate); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2ce0046ca27..f25224d1e36 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1122,6 +1122,7 @@ impl<'a> Parser<'a> { self.expected_tokens.push(TokenType::Keyword(kw::Crate)); if self.is_crate_vis() { self.bump(); // `crate` + self.sess.gated_spans.crate_visibility_modifier.borrow_mut().push(self.prev_span); return Ok(respan(self.prev_span, VisibilityKind::Crate(CrateSugar::JustCrate))); } diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 67a530ec683..97b1092452a 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -252,6 +252,7 @@ impl<'a> Parser<'a> { self.last_type_ascription = Some((self.prev_span, maybe_path)); lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?; + self.sess.gated_spans.type_ascription.borrow_mut().push(lhs.span); continue } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq { // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to @@ -453,7 +454,9 @@ impl<'a> Parser<'a> { self.bump(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; - (lo.to(span), ExprKind::Box(e)) + let span = lo.to(span); + self.sess.gated_spans.box_syntax.borrow_mut().push(span); + (span, ExprKind::Box(e)) } token::Ident(..) if self.token.is_ident_named(sym::not) => { // `not` is just an ordinary identifier in Rust-the-language, @@ -1260,6 +1263,10 @@ impl<'a> Parser<'a> { blk_mode: BlockCheckMode, outer_attrs: ThinVec<Attribute>, ) -> PResult<'a, P<Expr>> { + if let Some(label) = opt_label { + self.sess.gated_spans.label_break_value.borrow_mut().push(label.ident.span); + } + self.expect(&token::OpenDelim(token::Brace))?; let mut attrs = outer_attrs; @@ -1646,7 +1653,9 @@ impl<'a> Parser<'a> { error.emit(); Err(error) } else { - Ok(self.mk_expr(span_lo.to(body.span), ExprKind::TryBlock(body), attrs)) + let span = span_lo.to(body.span); + self.sess.gated_spans.try_blocks.borrow_mut().push(span); + Ok(self.mk_expr(span, ExprKind::TryBlock(body), attrs)) } } diff --git a/src/libsyntax/parse/parser/generics.rs b/src/libsyntax/parse/parser/generics.rs index bfcb0042a75..51caae69c86 100644 --- a/src/libsyntax/parse/parser/generics.rs +++ b/src/libsyntax/parse/parser/generics.rs @@ -55,11 +55,15 @@ impl<'a> Parser<'a> { } fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> { + let lo = self.token.span; + self.expect_keyword(kw::Const)?; let ident = self.parse_ident()?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; + self.sess.gated_spans.const_generics.borrow_mut().push(lo.to(self.prev_span)); + Ok(GenericParam { ident, id: ast::DUMMY_NODE_ID, diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 73bd80e2a21..95bddb5afdd 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -211,7 +211,7 @@ impl<'a> Parser<'a> { { // UNSAFE TRAIT ITEM self.bump(); // `unsafe` - let info = self.parse_item_trait(Unsafety::Unsafe)?; + let info = self.parse_item_trait(lo, Unsafety::Unsafe)?; return self.mk_item_with_info(attrs, lo, vis, info); } @@ -289,7 +289,7 @@ impl<'a> Parser<'a> { && self.is_keyword_ahead(1, &[kw::Trait])) { // TRAIT ITEM - let info = self.parse_item_trait(Unsafety::Normal)?; + let info = self.parse_item_trait(lo, Unsafety::Normal)?; return self.mk_item_with_info(attrs, lo, vis, info); } @@ -780,7 +780,7 @@ impl<'a> Parser<'a> { } /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. - fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> { + fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> { // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes @@ -793,29 +793,43 @@ impl<'a> Parser<'a> { let mut tps = self.parse_generics()?; // Parse optional colon and supertrait bounds. - let bounds = if self.eat(&token::Colon) { + let had_colon = self.eat(&token::Colon); + let span_at_colon = self.prev_span; + let bounds = if had_colon { self.parse_generic_bounds(Some(self.prev_span))? } else { Vec::new() }; + let span_before_eq = self.prev_span; if self.eat(&token::Eq) { // It's a trait alias. + if had_colon { + let span = span_at_colon.to(span_before_eq); + self.struct_span_err(span, "bounds are not allowed on trait aliases") + .emit(); + } + let bounds = self.parse_generic_bounds(None)?; tps.where_clause = self.parse_where_clause()?; self.expect(&token::Semi)?; + + let whole_span = lo.to(self.prev_span); if is_auto == IsAuto::Yes { let msg = "trait aliases cannot be `auto`"; - self.struct_span_err(self.prev_span, msg) - .span_label(self.prev_span, msg) + self.struct_span_err(whole_span, msg) + .span_label(whole_span, msg) .emit(); } if unsafety != Unsafety::Normal { let msg = "trait aliases cannot be `unsafe`"; - self.struct_span_err(self.prev_span, msg) - .span_label(self.prev_span, msg) + self.struct_span_err(whole_span, msg) + .span_label(whole_span, msg) .emit(); } + + self.sess.gated_spans.trait_alias.borrow_mut().push(whole_span); + Ok((ident, ItemKind::TraitAlias(tps, bounds), None)) } else { // It's a normal trait. @@ -1692,6 +1706,11 @@ impl<'a> Parser<'a> { }; let span = lo.to(self.prev_span); + + if !def.legacy { + self.sess.gated_spans.decl_macro.borrow_mut().push(span); + } + Ok(Some(self.mk_item(span, ident, ItemKind::MacroDef(def), vis.clone(), attrs.to_vec()))) } diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index af795e51792..969d5dd8374 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -324,7 +324,9 @@ impl<'a> Parser<'a> { self.parse_pat_ident(BindingMode::ByRef(mutbl))? } else if self.eat_keyword(kw::Box) { // Parse `box pat` - PatKind::Box(self.parse_pat_with_range_pat(false, None)?) + let pat = self.parse_pat_with_range_pat(false, None)?; + self.sess.gated_spans.box_patterns.borrow_mut().push(lo.to(self.prev_span)); + PatKind::Box(pat) } else if self.can_be_ident_pat() { // Parse `ident @ pat` // This can give false positives and parse nullary enums, @@ -609,6 +611,11 @@ impl<'a> Parser<'a> { Ok(PatKind::Mac(mac)) } + fn excluded_range_end(&self, span: Span) -> RangeEnd { + self.sess.gated_spans.exclusive_range_pattern.borrow_mut().push(span); + RangeEnd::Excluded + } + /// Parse a range pattern `$path $form $end?` where `$form = ".." | "..." | "..=" ;`. /// The `$path` has already been parsed and the next token is the `$form`. fn parse_pat_range_starting_with_path( @@ -618,7 +625,7 @@ impl<'a> Parser<'a> { path: Path ) -> PResult<'a, PatKind> { let (end_kind, form) = match self.token.kind { - token::DotDot => (RangeEnd::Excluded, ".."), + token::DotDot => (self.excluded_range_end(self.token.span), ".."), token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."), token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="), _ => panic!("can only parse `..`/`...`/`..=` for ranges (checked above)"), @@ -641,7 +648,7 @@ impl<'a> Parser<'a> { } else if self.eat(&token::DotDotEq) { (RangeEnd::Included(RangeSyntax::DotDotEq), "..=") } else if self.eat(&token::DotDot) { - (RangeEnd::Excluded, "..") + (self.excluded_range_end(op_span), "..") } else { panic!("impossible case: we already matched on a range-operator token") }; diff --git a/src/libsyntax/parse/parser/path.rs b/src/libsyntax/parse/parser/path.rs index 639d61a2b5c..77709a22953 100644 --- a/src/libsyntax/parse/parser/path.rs +++ b/src/libsyntax/parse/parser/path.rs @@ -404,8 +404,9 @@ impl<'a> Parser<'a> { // Parse lifetime argument. args.push(GenericArg::Lifetime(self.expect_lifetime())); misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints); - } else if self.check_ident() && self.look_ahead(1, - |t| t == &token::Eq || t == &token::Colon) { + } else if self.check_ident() + && self.look_ahead(1, |t| t == &token::Eq || t == &token::Colon) + { // Parse associated type constraint. let lo = self.token.span; let ident = self.parse_ident()?; @@ -420,7 +421,14 @@ impl<'a> Parser<'a> { } else { unreachable!(); }; + let span = lo.to(self.prev_span); + + // Gate associated type bounds, e.g., `Iterator<Item: Ord>`. + if let AssocTyConstraintKind::Bound { .. } = kind { + self.sess.gated_spans.associated_type_bounds.borrow_mut().push(span); + } + constraints.push(AssocTyConstraint { id: ast::DUMMY_NODE_ID, ident, diff --git a/src/libsyntax/sess.rs b/src/libsyntax/sess.rs index e49d3954f8e..28a0868d5dd 100644 --- a/src/libsyntax/sess.rs +++ b/src/libsyntax/sess.rs @@ -30,6 +30,28 @@ crate struct GatedSpans { crate or_patterns: Lock<Vec<Span>>, /// Spans collected for gating `const_extern_fn`, e.g. `const extern fn foo`. crate const_extern_fn: Lock<Vec<Span>>, + /// Spans collected for gating `trait_alias`, e.g. `trait Foo = Ord + Eq;`. + pub trait_alias: Lock<Vec<Span>>, + /// Spans collected for gating `associated_type_bounds`, e.g. `Iterator<Item: Ord>`. + pub associated_type_bounds: Lock<Vec<Span>>, + /// Spans collected for gating `crate_visibility_modifier`, e.g. `crate fn`. + pub crate_visibility_modifier: Lock<Vec<Span>>, + /// Spans collected for gating `const_generics`, e.g. `const N: usize`. + pub const_generics: Lock<Vec<Span>>, + /// Spans collected for gating `decl_macro`, e.g. `macro m() {}`. + pub decl_macro: Lock<Vec<Span>>, + /// Spans collected for gating `box_patterns`, e.g. `box 0`. + pub box_patterns: Lock<Vec<Span>>, + /// Spans collected for gating `exclusive_range_pattern`, e.g. `0..2`. + pub exclusive_range_pattern: Lock<Vec<Span>>, + /// Spans collected for gating `try_blocks`, e.g. `try { a? + b? }`. + pub try_blocks: Lock<Vec<Span>>, + /// Spans collected for gating `label_break_value`, e.g. `'label: { ... }`. + pub label_break_value: Lock<Vec<Span>>, + /// Spans collected for gating `box_syntax`, e.g. `box $expr`. + pub box_syntax: Lock<Vec<Span>>, + /// Spans collected for gating `type_ascription`, e.g. `42: usize`. + pub type_ascription: Lock<Vec<Span>>, } /// Info about a parsing session. |
