diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index b5db3331d0447..9b555df4b92de 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1472,15 +1472,17 @@ fn check_enum<'tcx>( Some(ref expr) => tcx.hir().span(expr.hir_id), None => v.span, }; + let display_discr = display_discriminant_value(tcx, v, discr.val); + let display_discr_i = display_discriminant_value(tcx, variant_i, disr_vals[i].val); struct_span_err!( tcx.sess, span, E0081, "discriminant value `{}` already exists", - disr_vals[i] + discr.val, ) - .span_label(i_span, format!("first use of `{}`", disr_vals[i])) - .span_label(span, format!("enum already has `{}`", disr_vals[i])) + .span_label(i_span, format!("first use of {}", display_discr_i)) + .span_label(span, format!("enum already has {}", display_discr)) .emit(); } disr_vals.push(discr); @@ -1490,6 +1492,25 @@ fn check_enum<'tcx>( check_transparent(tcx, sp, def); } +/// Format an enum discriminant value for use in a diagnostic message. +fn display_discriminant_value<'tcx>( + tcx: TyCtxt<'tcx>, + variant: &hir::Variant<'_>, + evaluated: u128, +) -> String { + if let Some(expr) = &variant.disr_expr { + let body = &tcx.hir().body(expr.body).value; + if let hir::ExprKind::Lit(lit) = &body.kind { + if let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node { + if evaluated != *lit_value { + return format!("`{}` (overflowed from `{}`)", evaluated, lit_value); + } + } + } + } + format!("`{}`", evaluated) +} + pub(super) fn check_type_params_are_used<'tcx>( tcx: TyCtxt<'tcx>, generics: &ty::Generics, diff --git a/src/test/ui/enum/enum-discrim-autosizing.rs b/src/test/ui/enum/enum-discrim-autosizing.rs index e9bb927597100..473a0ad6f7a13 100644 --- a/src/test/ui/enum/enum-discrim-autosizing.rs +++ b/src/test/ui/enum/enum-discrim-autosizing.rs @@ -4,8 +4,10 @@ // so force the repr. #[cfg_attr(not(target_pointer_width = "32"), repr(i32))] enum Eu64 { - Au64 = 0, - Bu64 = 0x8000_0000_0000_0000 //~ERROR already exists + Au64 = 0, //~NOTE first use of `0` + Bu64 = 0x8000_0000_0000_0000 + //~^ ERROR discriminant value `0` already exists + //~| NOTE enum already has `0` (overflowed from `9223372036854775808`) } fn main() {} diff --git a/src/test/ui/enum/enum-discrim-autosizing.stderr b/src/test/ui/enum/enum-discrim-autosizing.stderr index 8848f984cfb7d..a0f39098a2e98 100644 --- a/src/test/ui/enum/enum-discrim-autosizing.stderr +++ b/src/test/ui/enum/enum-discrim-autosizing.stderr @@ -4,7 +4,7 @@ error[E0081]: discriminant value `0` already exists LL | Au64 = 0, | - first use of `0` LL | Bu64 = 0x8000_0000_0000_0000 - | ^^^^^^^^^^^^^^^^^^^^^ enum already has `0` + | ^^^^^^^^^^^^^^^^^^^^^ enum already has `0` (overflowed from `9223372036854775808`) error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0081.rs b/src/test/ui/error-codes/E0081.rs index 33c8c14306bd1..255e05ced19f7 100644 --- a/src/test/ui/error-codes/E0081.rs +++ b/src/test/ui/error-codes/E0081.rs @@ -1,9 +1,20 @@ enum Enum { P = 3, + //~^ NOTE first use of `3` X = 3, //~^ ERROR discriminant value `3` already exists + //~| NOTE enum already has `3` Y = 5 } +#[repr(u8)] +enum EnumOverflowRepr { + P = 257, + //~^ NOTE first use of `1` (overflowed from `257`) + X = 513, + //~^ ERROR discriminant value `1` already exists + //~| NOTE enum already has `1` (overflowed from `513`) +} + fn main() { } diff --git a/src/test/ui/error-codes/E0081.stderr b/src/test/ui/error-codes/E0081.stderr index 0b3d351e1ac9a..9b279bb0214c6 100644 --- a/src/test/ui/error-codes/E0081.stderr +++ b/src/test/ui/error-codes/E0081.stderr @@ -1,11 +1,21 @@ error[E0081]: discriminant value `3` already exists - --> $DIR/E0081.rs:3:9 + --> $DIR/E0081.rs:4:9 | LL | P = 3, | - first use of `3` +LL | LL | X = 3, | ^ enum already has `3` -error: aborting due to previous error +error[E0081]: discriminant value `1` already exists + --> $DIR/E0081.rs:14:9 + | +LL | P = 257, + | --- first use of `1` (overflowed from `257`) +LL | +LL | X = 513, + | ^^^ enum already has `1` (overflowed from `513`) + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0081`.