about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorAndy Russell <arussell123@gmail.com>2019-05-22 16:56:51 -0400
committerAndy Russell <arussell123@gmail.com>2019-05-23 11:13:48 -0400
commit3cbf5864a6b7088eb28da30b9ccf61ba8d90054f (patch)
tree7afa8409d7057cf1b860df2ead27eb85cda61fab /src/libsyntax
parentf688ba608923bdbf6b46ec65af2f6464b6233a75 (diff)
downloadrust-3cbf5864a6b7088eb28da30b9ccf61ba8d90054f.tar.gz
rust-3cbf5864a6b7088eb28da30b9ccf61ba8d90054f.zip
tweak discriminant on non-nullary enum diagnostic
Adds notes pointing at the non-nullary variants, and uses "custom
discriminant" language to be consistent with the Reference.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/parse/diagnostics.rs47
-rw-r--r--src/libsyntax/parse/parser.rs14
2 files changed, 45 insertions, 16 deletions
diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs
index d48fcbbd672..8ac5beb21b5 100644
--- a/src/libsyntax/parse/diagnostics.rs
+++ b/src/libsyntax/parse/diagnostics.rs
@@ -1,16 +1,19 @@
 use crate::ast;
-use crate::ast::{BlockCheckMode, Expr, ExprKind, Item, ItemKind, Pat, PatKind, QSelf, Ty, TyKind};
-use crate::parse::parser::{BlockMode, PathStyle, TokenType, SemiColonMode};
+use crate::ast::{
+    BlockCheckMode, Expr, ExprKind, Item, ItemKind, Pat, PatKind, QSelf, Ty, TyKind, VariantData,
+};
+use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType};
 use crate::parse::token;
 use crate::parse::PResult;
 use crate::parse::Parser;
 use crate::print::pprust;
 use crate::ptr::P;
+use crate::source_map::Spanned;
 use crate::symbol::kw;
 use crate::ThinVec;
 use errors::{Applicability, DiagnosticBuilder};
-use syntax_pos::Span;
 use log::debug;
+use syntax_pos::Span;
 
 pub trait RecoverQPath: Sized + 'static {
     const PATH_STYLE: PathStyle = PathStyle::Expr;
@@ -79,6 +82,44 @@ impl<'a> Parser<'a> {
         }
     }
 
+    crate fn maybe_report_invalid_custom_discriminants(
+        &mut self,
+        discriminant_spans: Vec<Span>,
+        variants: &[Spanned<ast::Variant_>],
+    ) {
+        let has_fields = variants.iter().any(|variant| match variant.node.data {
+            VariantData::Tuple(..) | VariantData::Struct(..) => true,
+            VariantData::Unit(..) => false,
+        });
+
+        if !discriminant_spans.is_empty() && has_fields {
+            let mut err = self.struct_span_err(
+                discriminant_spans.clone(),
+                "custom discriminant values are not allowed in enums with fields",
+            );
+            for sp in discriminant_spans {
+                err.span_label(sp, "invalid 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),
+                    );
+
+                }
+            }
+            err.emit();
+        }
+    }
+
     crate fn maybe_recover_from_bad_type_plus(
         &mut self,
         allow_plus: bool,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 7600d6078a1..8f8473c483d 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -7464,7 +7464,6 @@ 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 all_nullary = true;
         let mut any_disr = vec![];
         while self.token != token::CloseDelim(token::Brace) {
             let variant_attrs = self.parse_outer_attributes()?;
@@ -7476,11 +7475,9 @@ impl<'a> Parser<'a> {
             let ident = self.parse_ident()?;
             if self.check(&token::OpenDelim(token::Brace)) {
                 // Parse a struct variant.
-                all_nullary = false;
                 let (fields, recovered) = self.parse_record_struct_body()?;
                 struct_def = VariantData::Struct(fields, recovered);
             } else if self.check(&token::OpenDelim(token::Paren)) {
-                all_nullary = false;
                 struct_def = VariantData::Tuple(
                     self.parse_tuple_struct_body()?,
                     ast::DUMMY_NODE_ID,
@@ -7524,16 +7521,7 @@ impl<'a> Parser<'a> {
             }
         }
         self.expect(&token::CloseDelim(token::Brace))?;
-        if !any_disr.is_empty() && !all_nullary {
-            let mut err = self.struct_span_err(
-                any_disr.clone(),
-                "discriminator values can only be used with a field-less enum",
-            );
-            for sp in any_disr {
-                err.span_label(sp, "only valid in field-less enums");
-            }
-            err.emit();
-        }
+        self.maybe_report_invalid_custom_discriminants(any_disr, &variants);
 
         Ok(ast::EnumDef { variants })
     }