]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #61056 - euclio:custom-discriminant-error, r=estebank
authorMazdak Farrokhzad <twingoow@gmail.com>
Thu, 23 May 2019 23:30:21 +0000 (01:30 +0200)
committerGitHub <noreply@github.com>
Thu, 23 May 2019 23:30:21 +0000 (01:30 +0200)
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.

Fixes #61039.

r? @estebank

src/libsyntax/parse/diagnostics.rs
src/libsyntax/parse/parser.rs
src/test/ui/parser/issue-17383.rs
src/test/ui/parser/issue-17383.stderr
src/test/ui/parser/tag-variant-disr-non-nullary.rs
src/test/ui/parser/tag-variant-disr-non-nullary.stderr

index d48fcbbd6720d96e4b27581e7e0d69e4af5544d9..8ac5beb21b5308405f13fba01b6a67725a07846f 100644 (file)
@@ -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,
index ae3665c834bd3e9c0b949a5281d3f4ff9eac5d34..df8015150823079401bac67b78bb8abe2bb0271c 100644 (file)
@@ -7466,7 +7466,6 @@ fn parse_existential_or_alias(
     /// 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()?;
@@ -7478,11 +7477,9 @@ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef>
             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,
@@ -7526,16 +7523,7 @@ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef>
             }
         }
         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 })
     }
index 04cd43d0b10714af5d02205711dbf05ea34b29e8..f95005cd914838605d401bc8ff71edb7c4f1f2ee 100644 (file)
@@ -1,6 +1,6 @@
 enum X {
     A = 3,
-    //~^ ERROR discriminator values can only be used with a field-less enum
+    //~^ ERROR custom discriminant values are not allowed in enums with fields
     B(usize)
 }
 
index 57caa3372a629dc076a17a7cc51f0e015c4f54ef..37abd0ff5e1f49cb8248347aae0f20f7d6bfb6d2 100644 (file)
@@ -1,8 +1,11 @@
-error: discriminator values can only be used with a field-less enum
+error: custom discriminant values are not allowed in enums with fields
   --> $DIR/issue-17383.rs:2:9
    |
 LL |     A = 3,
-   |         ^ only valid in field-less enums
+   |         ^ invalid custom discriminant
+LL |
+LL |     B(usize)
+   |     -------- variant with a field defined here
 
 error: aborting due to previous error
 
index 83a3b727982b5401e648ab537302ba7ad03dc6a7..305edc4ad5a0489d3e178abfad86a064ba651ec2 100644 (file)
@@ -1,11 +1,12 @@
 enum Color {
     Red = 0xff0000,
-    //~^ ERROR discriminator values can only be used with a field-less enum
+    //~^ ERROR custom discriminant values are not allowed in enums with fields
     Green = 0x00ff00,
     Blue = 0x0000ff,
     Black = 0x000000,
     White = 0xffffff,
     Other(usize),
+    Other2(usize, usize),
 }
 
 fn main() {}
index 884e9672cb12d205af85672ddc3c4dfeba054739..2d3b28395312438439814cdf3067eb0c6a8aab5c 100644 (file)
@@ -1,17 +1,21 @@
-error: discriminator values can only be used with a field-less enum
+error: custom discriminant values are not allowed in enums with fields
   --> $DIR/tag-variant-disr-non-nullary.rs:2:11
    |
 LL |     Red = 0xff0000,
-   |           ^^^^^^^^ only valid in field-less enums
+   |           ^^^^^^^^ invalid custom discriminant
 LL |
 LL |     Green = 0x00ff00,
-   |             ^^^^^^^^ only valid in field-less enums
+   |             ^^^^^^^^ invalid custom discriminant
 LL |     Blue = 0x0000ff,
-   |            ^^^^^^^^ only valid in field-less enums
+   |            ^^^^^^^^ invalid custom discriminant
 LL |     Black = 0x000000,
-   |             ^^^^^^^^ only valid in field-less enums
+   |             ^^^^^^^^ invalid custom discriminant
 LL |     White = 0xffffff,
-   |             ^^^^^^^^ only valid in field-less enums
+   |             ^^^^^^^^ invalid custom discriminant
+LL |     Other(usize),
+   |     ------------ variant with a field defined here
+LL |     Other2(usize, usize),
+   |     -------------------- variant with fields defined here
 
 error: aborting due to previous error