1
Fork 0

Auto merge of #97456 - Bryysen:issue-97319-fix, r=compiler-errors

Improve error message for E0081

Closes #97319
This commit is contained in:
bors 2022-05-29 12:00:30 +00:00
commit abc7681a76
9 changed files with 174 additions and 76 deletions

View file

@ -1376,6 +1376,8 @@ fn check_enum<'tcx>(
} }
let mut disr_vals: Vec<Discr<'tcx>> = Vec::with_capacity(vs.len()); let mut disr_vals: Vec<Discr<'tcx>> = Vec::with_capacity(vs.len());
// This tracks the previous variant span (in the loop) incase we need it for diagnostics
let mut prev_variant_span: Span = DUMMY_SP;
for ((_, discr), v) in iter::zip(def.discriminants(tcx), vs) { for ((_, discr), v) in iter::zip(def.discriminants(tcx), vs) {
// Check for duplicate discriminant values // Check for duplicate discriminant values
if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) { if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) {
@ -1390,42 +1392,59 @@ fn check_enum<'tcx>(
Some(ref expr) => tcx.hir().span(expr.hir_id), Some(ref expr) => tcx.hir().span(expr.hir_id),
None => v.span, None => v.span,
}; };
let display_discr = display_discriminant_value(tcx, v, discr.val); let display_discr = format_discriminant_overflow(tcx, v, discr);
let display_discr_i = display_discriminant_value(tcx, variant_i, disr_vals[i].val); let display_discr_i = format_discriminant_overflow(tcx, variant_i, disr_vals[i]);
struct_span_err!( let no_disr = v.disr_expr.is_none();
let mut err = struct_span_err!(
tcx.sess, tcx.sess,
span, sp,
E0081, E0081,
"discriminant value `{}` already exists", "discriminant value `{}` assigned more than once",
discr.val, discr,
) );
.span_label(i_span, format!("first use of {display_discr_i}"))
.span_label(span, format!("enum already has {display_discr}")) err.span_label(i_span, format!("first assignment of {display_discr_i}"));
.emit(); err.span_label(span, format!("second assignment of {display_discr}"));
if no_disr {
err.span_label(
prev_variant_span,
format!(
"assigned discriminant for `{}` was incremented from this discriminant",
v.ident
),
);
} }
err.emit();
}
disr_vals.push(discr); disr_vals.push(discr);
prev_variant_span = v.span;
} }
check_representable(tcx, sp, def_id); check_representable(tcx, sp, def_id);
check_transparent(tcx, sp, def); check_transparent(tcx, sp, def);
} }
/// Format an enum discriminant value for use in a diagnostic message. /// In the case that a discriminant is both a duplicate and an overflowing literal,
fn display_discriminant_value<'tcx>( /// we insert both the assigned discriminant and the literal it overflowed from into the formatted
/// output. Otherwise we format the discriminant normally.
fn format_discriminant_overflow<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
variant: &hir::Variant<'_>, variant: &hir::Variant<'_>,
evaluated: u128, dis: Discr<'tcx>,
) -> String { ) -> String {
if let Some(expr) = &variant.disr_expr { if let Some(expr) = &variant.disr_expr {
let body = &tcx.hir().body(expr.body).value; let body = &tcx.hir().body(expr.body).value;
if let hir::ExprKind::Lit(lit) = &body.kind if let hir::ExprKind::Lit(lit) = &body.kind
&& let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
&& evaluated != *lit_value && dis.val != *lit_value
{ {
return format!("`{evaluated}` (overflowed from `{lit_value}`)"); return format!("`{dis}` (overflowed from `{lit_value}`)");
} }
} }
format!("`{}`", evaluated)
format!("`{dis}`")
} }
pub(super) fn check_type_params_are_used<'tcx>( pub(super) fn check_type_params_are_used<'tcx>(

View file

@ -4,10 +4,11 @@
// so force the repr. // so force the repr.
#[cfg_attr(not(target_pointer_width = "32"), repr(i32))] #[cfg_attr(not(target_pointer_width = "32"), repr(i32))]
enum Eu64 { enum Eu64 {
Au64 = 0, //~NOTE first use of `0` //~^ ERROR discriminant value `0` assigned more than once
Au64 = 0,
//~^NOTE first assignment of `0`
Bu64 = 0x8000_0000_0000_0000 Bu64 = 0x8000_0000_0000_0000
//~^ ERROR discriminant value `0` already exists //~^NOTE second assignment of `0` (overflowed from `9223372036854775808`)
//~| NOTE enum already has `0` (overflowed from `9223372036854775808`)
} }
fn main() {} fn main() {}

View file

@ -1,10 +1,16 @@
error[E0081]: discriminant value `0` already exists error[E0081]: discriminant value `0` assigned more than once
--> $DIR/enum-discrim-autosizing.rs:8:12 --> $DIR/enum-discrim-autosizing.rs:6:1
| |
LL | Au64 = 0, LL | / enum Eu64 {
| - first use of `0` LL | |
LL | Bu64 = 0x8000_0000_0000_0000 LL | | Au64 = 0,
| ^^^^^^^^^^^^^^^^^^^^^ enum already has `0` (overflowed from `9223372036854775808`) | | - first assignment of `0`
LL | |
LL | | Bu64 = 0x8000_0000_0000_0000
| | --------------------- second assignment of `0` (overflowed from `9223372036854775808`)
LL | |
LL | | }
| |_^
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,19 +1,30 @@
enum Enum { enum Enum {
//~^ ERROR discriminant value `3` assigned more than once
P = 3, P = 3,
//~^ NOTE first use of `3` //~^ NOTE first assignment of `3`
X = 3, X = 3,
//~^ ERROR discriminant value `3` already exists //~^ NOTE second assignment of `3`
//~| NOTE enum already has `3`
Y = 5 Y = 5
} }
#[repr(u8)] #[repr(u8)]
enum EnumOverflowRepr { enum EnumOverflowRepr {
//~^ ERROR discriminant value `1` assigned more than once
P = 257, P = 257,
//~^ NOTE first use of `1` (overflowed from `257`) //~^ NOTE first assignment of `1` (overflowed from `257`)
X = 513, X = 513,
//~^ ERROR discriminant value `1` already exists //~^ NOTE second assignment of `1` (overflowed from `513`)
//~| NOTE enum already has `1` (overflowed from `513`) }
#[repr(i8)]
enum NegDisEnum {
//~^ ERROR discriminant value `-1` assigned more than once
First = -1,
//~^ NOTE first assignment of `-1`
Second = -2,
//~^ NOTE assigned discriminant for `Last` was incremented from this discriminant
Last,
//~^ NOTE second assignment of `-1`
} }
fn main() { fn main() {

View file

@ -1,21 +1,49 @@
error[E0081]: discriminant value `3` already exists error[E0081]: discriminant value `3` assigned more than once
--> $DIR/E0081.rs:4:9 --> $DIR/E0081.rs:1:1
| |
LL | P = 3, LL | / enum Enum {
| - first use of `3` LL | |
LL | LL | | P = 3,
LL | X = 3, | | - first assignment of `3`
| ^ enum already has `3` LL | |
LL | | X = 3,
| | - second assignment of `3`
LL | |
LL | | Y = 5
LL | | }
| |_^
error[E0081]: discriminant value `1` already exists error[E0081]: discriminant value `1` assigned more than once
--> $DIR/E0081.rs:14:9 --> $DIR/E0081.rs:11:1
| |
LL | P = 257, LL | / enum EnumOverflowRepr {
| --- first use of `1` (overflowed from `257`) LL | |
LL | LL | | P = 257,
LL | X = 513, | | --- first assignment of `1` (overflowed from `257`)
| ^^^ enum already has `1` (overflowed from `513`) LL | |
LL | | X = 513,
| | --- second assignment of `1` (overflowed from `513`)
LL | |
LL | | }
| |_^
error: aborting due to 2 previous errors error[E0081]: discriminant value `-1` assigned more than once
--> $DIR/E0081.rs:20:1
|
LL | / enum NegDisEnum {
LL | |
LL | | First = -1,
| | -- first assignment of `-1`
LL | |
LL | | Second = -2,
| | ----------- assigned discriminant for `Last` was incremented from this discriminant
LL | |
LL | | Last,
| | ---- second assignment of `-1`
LL | |
LL | | }
| |_^
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0081`. For more information about this error, try `rustc --explain E0081`.

View file

@ -1,15 +1,15 @@
const N: isize = 1; const N: isize = 1;
enum Foo { enum Foo {
//~^ ERROR discriminant value `1` assigned more than once
//~| ERROR discriminant value `1` assigned more than once
//~| ERROR discriminant value `1` assigned more than once
A = 1, A = 1,
B = 1, B = 1,
//~^ ERROR discriminant value `1` already exists
C = 0, C = 0,
D, D,
//~^ ERROR discriminant value `1` already exists
E = N, E = N,
//~^ ERROR discriminant value `1` already exists
} }

View file

@ -1,28 +1,53 @@
error[E0081]: discriminant value `1` already exists error[E0081]: discriminant value `1` assigned more than once
--> $DIR/issue-15524.rs:5:9 --> $DIR/issue-15524.rs:3:1
| |
LL | A = 1, LL | / enum Foo {
| - first use of `1` LL | |
LL | B = 1, LL | |
| ^ enum already has `1` LL | |
LL | | A = 1,
| | - first assignment of `1`
LL | | B = 1,
| | - second assignment of `1`
... |
LL | |
LL | | }
| |_^
error[E0081]: discriminant value `1` already exists error[E0081]: discriminant value `1` assigned more than once
--> $DIR/issue-15524.rs:8:5 --> $DIR/issue-15524.rs:3:1
| |
LL | A = 1, LL | / enum Foo {
| - first use of `1` LL | |
... LL | |
LL | D, LL | |
| ^ enum already has `1` LL | | A = 1,
| | - first assignment of `1`
LL | | B = 1,
LL | | C = 0,
| | ----- assigned discriminant for `D` was incremented from this discriminant
LL | | D,
| | - second assignment of `1`
... |
LL | |
LL | | }
| |_^
error[E0081]: discriminant value `1` already exists error[E0081]: discriminant value `1` assigned more than once
--> $DIR/issue-15524.rs:11:9 --> $DIR/issue-15524.rs:3:1
| |
LL | A = 1, LL | / enum Foo {
| - first use of `1` LL | |
... LL | |
LL | E = N, LL | |
| ^ enum already has `1` LL | | A = 1,
| | - first assignment of `1`
... |
LL | | E = N,
| | - second assignment of `1`
LL | |
LL | | }
| |_^
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -1,11 +1,12 @@
// Black and White have the same discriminator value ... // Black and White have the same discriminator value ...
enum Color { enum Color {
//~^ ERROR discriminant value `0` assigned more than once
Red = 0xff0000, Red = 0xff0000,
Green = 0x00ff00, Green = 0x00ff00,
Blue = 0x0000ff, Blue = 0x0000ff,
Black = 0x000000, Black = 0x000000,
White = 0x000000, //~ ERROR discriminant value `0` already exists White = 0x000000,
} }
fn main() { } fn main() { }

View file

@ -1,10 +1,17 @@
error[E0081]: discriminant value `0` already exists error[E0081]: discriminant value `0` assigned more than once
--> $DIR/tag-variant-disr-dup.rs:8:13 --> $DIR/tag-variant-disr-dup.rs:3:1
| |
LL | Black = 0x000000, LL | / enum Color {
| -------- first use of `0` LL | |
LL | White = 0x000000, LL | | Red = 0xff0000,
| ^^^^^^^^ enum already has `0` LL | | Green = 0x00ff00,
LL | | Blue = 0x0000ff,
LL | | Black = 0x000000,
| | -------- first assignment of `0`
LL | | White = 0x000000,
| | -------- second assignment of `0`
LL | | }
| |_^
error: aborting due to previous error error: aborting due to previous error