about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorJohn Wrenn <john_wrenn@brown.edu>2019-05-09 17:08:55 -0400
committerJohn Wrenn <john_wrenn@brown.edu>2019-06-21 11:00:10 -0400
commitac98342e846e79985f0c4969a2d546dee24a70d1 (patch)
tree8c2ff20debabdd8f9c9f7476f1b2d3868192f6cd /src/libsyntax/parse
parent38cd9489f75f4a4387296ee304e2287f7c32c211 (diff)
downloadrust-ac98342e846e79985f0c4969a2d546dee24a70d1.tar.gz
rust-ac98342e846e79985f0c4969a2d546dee24a70d1.zip
Implement arbitrary_enum_discriminant
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/diagnostics.rs48
-rw-r--r--src/libsyntax/parse/parser.rs31
2 files changed, 43 insertions, 36 deletions
diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs
index 60544cca877..07fe521edb0 100644
--- a/src/libsyntax/parse/diagnostics.rs
+++ b/src/libsyntax/parse/diagnostics.rs
@@ -2,7 +2,7 @@ use crate::ast::{
     self, Arg, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind,
     Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, VariantData,
 };
-use crate::parse::{SeqSep, PResult, Parser};
+use crate::parse::{SeqSep, PResult, Parser, ParseSess};
 use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType};
 use crate::parse::token::{self, TokenKind};
 use crate::print::pprust;
@@ -539,8 +539,7 @@ impl<'a> Parser<'a> {
     }
 
     crate fn maybe_report_invalid_custom_discriminants(
-        &mut self,
-        discriminant_spans: Vec<Span>,
+        sess: &ParseSess,
         variants: &[Spanned<ast::Variant_>],
     ) {
         let has_fields = variants.iter().any(|variant| match variant.node.data {
@@ -548,28 +547,39 @@ impl<'a> Parser<'a> {
             VariantData::Unit(..) => false,
         });
 
+        let discriminant_spans = variants.iter().filter(|variant| match variant.node.data {
+            VariantData::Tuple(..) | VariantData::Struct(..) => false,
+            VariantData::Unit(..) => true,
+        })
+        .filter_map(|variant| variant.node.disr_expr.as_ref().map(|c| c.value.span))
+        .collect::<Vec<_>>();
+
         if !discriminant_spans.is_empty() && has_fields {
-            let mut err = self.struct_span_err(
+            let mut err = crate::feature_gate::feature_err(
+                sess,
+                sym::arbitrary_enum_discriminant,
                 discriminant_spans.clone(),
-                "custom discriminant values are not allowed in enums with fields",
+                crate::feature_gate::GateIssue::Language,
+                "custom discriminant values are not allowed in enums with tuple or struct variants",
             );
             for sp in discriminant_spans {
-                err.span_label(sp, "invalid custom discriminant");
+                err.span_label(sp, "disallowed custom discriminant");
             }
             for variant in variants.iter() {
-                if let VariantData::Struct(fields, ..) | VariantData::Tuple(fields, ..) =
-                    &variant.node.data
-                {
-                    let fields = if fields.len() > 1 {
-                        "fields"
-                    } else {
-                        "a field"
-                    };
-                    err.span_label(
-                        variant.span,
-                        &format!("variant with {fields} defined here", fields = fields),
-                    );
-
+                match &variant.node.data {
+                    VariantData::Struct(..) => {
+                        err.span_label(
+                            variant.span,
+                            "struct variant defined here",
+                        );
+                    }
+                    VariantData::Tuple(..) => {
+                        err.span_label(
+                            variant.span,
+                            "tuple variant defined here",
+                        );
+                    }
+                    VariantData::Unit(..) => {}
                 }
             }
             err.emit();
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index fa697e06d26..2718ddded29 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -6963,36 +6963,34 @@ impl<'a> Parser<'a> {
     /// Parses the part of an enum declaration following the `{`.
     fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> {
         let mut variants = Vec::new();
-        let mut any_disr = vec![];
         while self.token != token::CloseDelim(token::Brace) {
             let variant_attrs = self.parse_outer_attributes()?;
             let vlo = self.token.span;
 
-            let struct_def;
-            let mut disr_expr = None;
             self.eat_bad_pub();
             let ident = self.parse_ident()?;
-            if self.check(&token::OpenDelim(token::Brace)) {
+
+            let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
                 // Parse a struct variant.
                 let (fields, recovered) = self.parse_record_struct_body()?;
-                struct_def = VariantData::Struct(fields, recovered);
+                VariantData::Struct(fields, recovered)
             } else if self.check(&token::OpenDelim(token::Paren)) {
-                struct_def = VariantData::Tuple(
+                VariantData::Tuple(
                     self.parse_tuple_struct_body()?,
                     ast::DUMMY_NODE_ID,
-                );
-            } else if self.eat(&token::Eq) {
-                disr_expr = Some(AnonConst {
+                )
+            } else {
+                VariantData::Unit(ast::DUMMY_NODE_ID)
+            };
+
+            let disr_expr = if self.eat(&token::Eq) {
+                Some(AnonConst {
                     id: ast::DUMMY_NODE_ID,
                     value: self.parse_expr()?,
-                });
-                if let Some(sp) = disr_expr.as_ref().map(|c| c.value.span) {
-                    any_disr.push(sp);
-                }
-                struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
+                })
             } else {
-                struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
-            }
+                None
+            };
 
             let vr = ast::Variant_ {
                 ident,
@@ -7020,7 +7018,6 @@ impl<'a> Parser<'a> {
             }
         }
         self.expect(&token::CloseDelim(token::Brace))?;
-        self.maybe_report_invalid_custom_discriminants(any_disr, &variants);
 
         Ok(ast::EnumDef { variants })
     }