Skip to content

Commit

Permalink
Rollup merge of rust-lang#61056 - euclio:custom-discriminant-error, r…
Browse files Browse the repository at this point in the history
…=estebank

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 rust-lang#61039.

r? @estebank
  • Loading branch information
Centril authored May 23, 2019
2 parents b9459e7 + 3cbf586 commit 26f3528
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 26 deletions.
47 changes: 44 additions & 3 deletions src/libsyntax/parse/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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,
Expand Down
14 changes: 1 addition & 13 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7466,7 +7466,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()?;
Expand All @@ -7478,11 +7477,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,
Expand Down Expand Up @@ -7526,16 +7523,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 })
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/parser/issue-17383.rs
Original file line number Diff line number Diff line change
@@ -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)
}

Expand Down
7 changes: 5 additions & 2 deletions src/test/ui/parser/issue-17383.stderr
Original file line number Diff line number Diff line change
@@ -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

3 changes: 2 additions & 1 deletion src/test/ui/parser/tag-variant-disr-non-nullary.rs
Original file line number Diff line number Diff line change
@@ -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() {}
16 changes: 10 additions & 6 deletions src/test/ui/parser/tag-variant-disr-non-nullary.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 26f3528

Please sign in to comment.