Auto merge of #97456 - Bryysen:issue-97319-fix, r=compiler-errors
Improve error message for E0081 Closes #97319
This commit is contained in:
commit
abc7681a76
9 changed files with 174 additions and 76 deletions
|
@ -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>(
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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() { }
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue