Skip to content

Commit 3cbf586

Browse files
committed
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.
1 parent f688ba6 commit 3cbf586

File tree

6 files changed

+63
-26
lines changed

6 files changed

+63
-26
lines changed

src/libsyntax/parse/diagnostics.rs

+44-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
use crate::ast;
2-
use crate::ast::{BlockCheckMode, Expr, ExprKind, Item, ItemKind, Pat, PatKind, QSelf, Ty, TyKind};
3-
use crate::parse::parser::{BlockMode, PathStyle, TokenType, SemiColonMode};
2+
use crate::ast::{
3+
BlockCheckMode, Expr, ExprKind, Item, ItemKind, Pat, PatKind, QSelf, Ty, TyKind, VariantData,
4+
};
5+
use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType};
46
use crate::parse::token;
57
use crate::parse::PResult;
68
use crate::parse::Parser;
79
use crate::print::pprust;
810
use crate::ptr::P;
11+
use crate::source_map::Spanned;
912
use crate::symbol::kw;
1013
use crate::ThinVec;
1114
use errors::{Applicability, DiagnosticBuilder};
12-
use syntax_pos::Span;
1315
use log::debug;
16+
use syntax_pos::Span;
1417

1518
pub trait RecoverQPath: Sized + 'static {
1619
const PATH_STYLE: PathStyle = PathStyle::Expr;
@@ -79,6 +82,44 @@ impl<'a> Parser<'a> {
7982
}
8083
}
8184

85+
crate fn maybe_report_invalid_custom_discriminants(
86+
&mut self,
87+
discriminant_spans: Vec<Span>,
88+
variants: &[Spanned<ast::Variant_>],
89+
) {
90+
let has_fields = variants.iter().any(|variant| match variant.node.data {
91+
VariantData::Tuple(..) | VariantData::Struct(..) => true,
92+
VariantData::Unit(..) => false,
93+
});
94+
95+
if !discriminant_spans.is_empty() && has_fields {
96+
let mut err = self.struct_span_err(
97+
discriminant_spans.clone(),
98+
"custom discriminant values are not allowed in enums with fields",
99+
);
100+
for sp in discriminant_spans {
101+
err.span_label(sp, "invalid custom discriminant");
102+
}
103+
for variant in variants.iter() {
104+
if let VariantData::Struct(fields, ..) | VariantData::Tuple(fields, ..) =
105+
&variant.node.data
106+
{
107+
let fields = if fields.len() > 1 {
108+
"fields"
109+
} else {
110+
"a field"
111+
};
112+
err.span_label(
113+
variant.span,
114+
&format!("variant with {fields} defined here", fields = fields),
115+
);
116+
117+
}
118+
}
119+
err.emit();
120+
}
121+
}
122+
82123
crate fn maybe_recover_from_bad_type_plus(
83124
&mut self,
84125
allow_plus: bool,

src/libsyntax/parse/parser.rs

+1-13
Original file line numberDiff line numberDiff line change
@@ -7464,7 +7464,6 @@ impl<'a> Parser<'a> {
74647464
/// Parses the part of an enum declaration following the `{`.
74657465
fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> {
74667466
let mut variants = Vec::new();
7467-
let mut all_nullary = true;
74687467
let mut any_disr = vec![];
74697468
while self.token != token::CloseDelim(token::Brace) {
74707469
let variant_attrs = self.parse_outer_attributes()?;
@@ -7476,11 +7475,9 @@ impl<'a> Parser<'a> {
74767475
let ident = self.parse_ident()?;
74777476
if self.check(&token::OpenDelim(token::Brace)) {
74787477
// Parse a struct variant.
7479-
all_nullary = false;
74807478
let (fields, recovered) = self.parse_record_struct_body()?;
74817479
struct_def = VariantData::Struct(fields, recovered);
74827480
} else if self.check(&token::OpenDelim(token::Paren)) {
7483-
all_nullary = false;
74847481
struct_def = VariantData::Tuple(
74857482
self.parse_tuple_struct_body()?,
74867483
ast::DUMMY_NODE_ID,
@@ -7524,16 +7521,7 @@ impl<'a> Parser<'a> {
75247521
}
75257522
}
75267523
self.expect(&token::CloseDelim(token::Brace))?;
7527-
if !any_disr.is_empty() && !all_nullary {
7528-
let mut err = self.struct_span_err(
7529-
any_disr.clone(),
7530-
"discriminator values can only be used with a field-less enum",
7531-
);
7532-
for sp in any_disr {
7533-
err.span_label(sp, "only valid in field-less enums");
7534-
}
7535-
err.emit();
7536-
}
7524+
self.maybe_report_invalid_custom_discriminants(any_disr, &variants);
75377525

75387526
Ok(ast::EnumDef { variants })
75397527
}

src/test/ui/parser/issue-17383.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
enum X {
22
A = 3,
3-
//~^ ERROR discriminator values can only be used with a field-less enum
3+
//~^ ERROR custom discriminant values are not allowed in enums with fields
44
B(usize)
55
}
66

src/test/ui/parser/issue-17383.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
error: discriminator values can only be used with a field-less enum
1+
error: custom discriminant values are not allowed in enums with fields
22
--> $DIR/issue-17383.rs:2:9
33
|
44
LL | A = 3,
5-
| ^ only valid in field-less enums
5+
| ^ invalid custom discriminant
6+
LL |
7+
LL | B(usize)
8+
| -------- variant with a field defined here
69

710
error: aborting due to previous error
811

Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
enum Color {
22
Red = 0xff0000,
3-
//~^ ERROR discriminator values can only be used with a field-less enum
3+
//~^ ERROR custom discriminant values are not allowed in enums with fields
44
Green = 0x00ff00,
55
Blue = 0x0000ff,
66
Black = 0x000000,
77
White = 0xffffff,
88
Other(usize),
9+
Other2(usize, usize),
910
}
1011

1112
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1-
error: discriminator values can only be used with a field-less enum
1+
error: custom discriminant values are not allowed in enums with fields
22
--> $DIR/tag-variant-disr-non-nullary.rs:2:11
33
|
44
LL | Red = 0xff0000,
5-
| ^^^^^^^^ only valid in field-less enums
5+
| ^^^^^^^^ invalid custom discriminant
66
LL |
77
LL | Green = 0x00ff00,
8-
| ^^^^^^^^ only valid in field-less enums
8+
| ^^^^^^^^ invalid custom discriminant
99
LL | Blue = 0x0000ff,
10-
| ^^^^^^^^ only valid in field-less enums
10+
| ^^^^^^^^ invalid custom discriminant
1111
LL | Black = 0x000000,
12-
| ^^^^^^^^ only valid in field-less enums
12+
| ^^^^^^^^ invalid custom discriminant
1313
LL | White = 0xffffff,
14-
| ^^^^^^^^ only valid in field-less enums
14+
| ^^^^^^^^ invalid custom discriminant
15+
LL | Other(usize),
16+
| ------------ variant with a field defined here
17+
LL | Other2(usize, usize),
18+
| -------------------- variant with fields defined here
1519

1620
error: aborting due to previous error
1721

0 commit comments

Comments
 (0)