diff options
| author | Andy Russell <arussell123@gmail.com> | 2019-05-22 16:56:51 -0400 |
|---|---|---|
| committer | Andy Russell <arussell123@gmail.com> | 2019-05-23 11:13:48 -0400 |
| commit | 3cbf5864a6b7088eb28da30b9ccf61ba8d90054f (patch) | |
| tree | 7afa8409d7057cf1b860df2ead27eb85cda61fab /src/libsyntax | |
| parent | f688ba608923bdbf6b46ec65af2f6464b6233a75 (diff) | |
| download | rust-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.rs | 47 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 14 |
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 }) } |
