Rollup merge of #61056 - euclio:custom-discriminant-error, r=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 #61039. r? @estebank
This commit is contained in:
commit
26f3528434
6 changed files with 63 additions and 26 deletions
|
@ -1,16 +1,19 @@
|
||||||
use crate::ast;
|
use crate::ast;
|
||||||
use crate::ast::{BlockCheckMode, Expr, ExprKind, Item, ItemKind, Pat, PatKind, QSelf, Ty, TyKind};
|
use crate::ast::{
|
||||||
use crate::parse::parser::{BlockMode, PathStyle, TokenType, SemiColonMode};
|
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::token;
|
||||||
use crate::parse::PResult;
|
use crate::parse::PResult;
|
||||||
use crate::parse::Parser;
|
use crate::parse::Parser;
|
||||||
use crate::print::pprust;
|
use crate::print::pprust;
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
|
use crate::source_map::Spanned;
|
||||||
use crate::symbol::kw;
|
use crate::symbol::kw;
|
||||||
use crate::ThinVec;
|
use crate::ThinVec;
|
||||||
use errors::{Applicability, DiagnosticBuilder};
|
use errors::{Applicability, DiagnosticBuilder};
|
||||||
use syntax_pos::Span;
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
use syntax_pos::Span;
|
||||||
|
|
||||||
pub trait RecoverQPath: Sized + 'static {
|
pub trait RecoverQPath: Sized + 'static {
|
||||||
const PATH_STYLE: PathStyle = PathStyle::Expr;
|
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(
|
crate fn maybe_recover_from_bad_type_plus(
|
||||||
&mut self,
|
&mut self,
|
||||||
allow_plus: bool,
|
allow_plus: bool,
|
||||||
|
|
|
@ -7466,7 +7466,6 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses the part of an enum declaration following the `{`.
|
/// Parses the part of an enum declaration following the `{`.
|
||||||
fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> {
|
fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> {
|
||||||
let mut variants = Vec::new();
|
let mut variants = Vec::new();
|
||||||
let mut all_nullary = true;
|
|
||||||
let mut any_disr = vec![];
|
let mut any_disr = vec![];
|
||||||
while self.token != token::CloseDelim(token::Brace) {
|
while self.token != token::CloseDelim(token::Brace) {
|
||||||
let variant_attrs = self.parse_outer_attributes()?;
|
let variant_attrs = self.parse_outer_attributes()?;
|
||||||
|
@ -7478,11 +7477,9 @@ impl<'a> Parser<'a> {
|
||||||
let ident = self.parse_ident()?;
|
let ident = self.parse_ident()?;
|
||||||
if self.check(&token::OpenDelim(token::Brace)) {
|
if self.check(&token::OpenDelim(token::Brace)) {
|
||||||
// Parse a struct variant.
|
// Parse a struct variant.
|
||||||
all_nullary = false;
|
|
||||||
let (fields, recovered) = self.parse_record_struct_body()?;
|
let (fields, recovered) = self.parse_record_struct_body()?;
|
||||||
struct_def = VariantData::Struct(fields, recovered);
|
struct_def = VariantData::Struct(fields, recovered);
|
||||||
} else if self.check(&token::OpenDelim(token::Paren)) {
|
} else if self.check(&token::OpenDelim(token::Paren)) {
|
||||||
all_nullary = false;
|
|
||||||
struct_def = VariantData::Tuple(
|
struct_def = VariantData::Tuple(
|
||||||
self.parse_tuple_struct_body()?,
|
self.parse_tuple_struct_body()?,
|
||||||
ast::DUMMY_NODE_ID,
|
ast::DUMMY_NODE_ID,
|
||||||
|
@ -7526,16 +7523,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.expect(&token::CloseDelim(token::Brace))?;
|
self.expect(&token::CloseDelim(token::Brace))?;
|
||||||
if !any_disr.is_empty() && !all_nullary {
|
self.maybe_report_invalid_custom_discriminants(any_disr, &variants);
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(ast::EnumDef { variants })
|
Ok(ast::EnumDef { variants })
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
enum X {
|
enum X {
|
||||||
A = 3,
|
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)
|
B(usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
--> $DIR/issue-17383.rs:2:9
|
||||||
|
|
|
|
||||||
LL | A = 3,
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
enum Color {
|
enum Color {
|
||||||
Red = 0xff0000,
|
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,
|
Green = 0x00ff00,
|
||||||
Blue = 0x0000ff,
|
Blue = 0x0000ff,
|
||||||
Black = 0x000000,
|
Black = 0x000000,
|
||||||
White = 0xffffff,
|
White = 0xffffff,
|
||||||
Other(usize),
|
Other(usize),
|
||||||
|
Other2(usize, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -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
|
--> $DIR/tag-variant-disr-non-nullary.rs:2:11
|
||||||
|
|
|
|
||||||
LL | Red = 0xff0000,
|
LL | Red = 0xff0000,
|
||||||
| ^^^^^^^^ only valid in field-less enums
|
| ^^^^^^^^ invalid custom discriminant
|
||||||
LL |
|
LL |
|
||||||
LL | Green = 0x00ff00,
|
LL | Green = 0x00ff00,
|
||||||
| ^^^^^^^^ only valid in field-less enums
|
| ^^^^^^^^ invalid custom discriminant
|
||||||
LL | Blue = 0x0000ff,
|
LL | Blue = 0x0000ff,
|
||||||
| ^^^^^^^^ only valid in field-less enums
|
| ^^^^^^^^ invalid custom discriminant
|
||||||
LL | Black = 0x000000,
|
LL | Black = 0x000000,
|
||||||
| ^^^^^^^^ only valid in field-less enums
|
| ^^^^^^^^ invalid custom discriminant
|
||||||
LL | White = 0xffffff,
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue