Skip to content

Commit 4c0ff4d

Browse files
committed
Show discriminant before overflow in diagnostic.
1 parent 8b50cc9 commit 4c0ff4d

File tree

5 files changed

+52
-8
lines changed

5 files changed

+52
-8
lines changed

compiler/rustc_typeck/src/check/check.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,15 +1472,17 @@ fn check_enum<'tcx>(
14721472
Some(ref expr) => tcx.hir().span(expr.hir_id),
14731473
None => v.span,
14741474
};
1475+
let display_discr = display_discriminant_value(tcx, v, discr.val);
1476+
let display_discr_i = display_discriminant_value(tcx, variant_i, disr_vals[i].val);
14751477
struct_span_err!(
14761478
tcx.sess,
14771479
span,
14781480
E0081,
14791481
"discriminant value `{}` already exists",
1480-
disr_vals[i]
1482+
discr.val,
14811483
)
1482-
.span_label(i_span, format!("first use of `{}`", disr_vals[i]))
1483-
.span_label(span, format!("enum already has `{}`", disr_vals[i]))
1484+
.span_label(i_span, format!("first use of {}", display_discr_i))
1485+
.span_label(span, format!("enum already has {}", display_discr))
14841486
.emit();
14851487
}
14861488
disr_vals.push(discr);
@@ -1490,6 +1492,25 @@ fn check_enum<'tcx>(
14901492
check_transparent(tcx, sp, def);
14911493
}
14921494

1495+
/// Format an enum discriminant value for use in a diagnostic message.
1496+
fn display_discriminant_value<'tcx>(
1497+
tcx: TyCtxt<'tcx>,
1498+
variant: &hir::Variant<'_>,
1499+
evaluated: u128,
1500+
) -> String {
1501+
if let Some(expr) = &variant.disr_expr {
1502+
let body = &tcx.hir().body(expr.body).value;
1503+
if let hir::ExprKind::Lit(lit) = &body.kind {
1504+
if let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node {
1505+
if evaluated != *lit_value {
1506+
return format!("`{}` (overflowed from `{}`)", evaluated, lit_value);
1507+
}
1508+
}
1509+
}
1510+
}
1511+
format!("`{}`", evaluated)
1512+
}
1513+
14931514
pub(super) fn check_type_params_are_used<'tcx>(
14941515
tcx: TyCtxt<'tcx>,
14951516
generics: &ty::Generics,

src/test/ui/enum/enum-discrim-autosizing.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
// so force the repr.
55
#[cfg_attr(not(target_pointer_width = "32"), repr(i32))]
66
enum Eu64 {
7-
Au64 = 0,
8-
Bu64 = 0x8000_0000_0000_0000 //~ERROR already exists
7+
Au64 = 0, //~NOTE first use of `0`
8+
Bu64 = 0x8000_0000_0000_0000
9+
//~^ ERROR discriminant value `0` already exists
10+
//~| NOTE enum already has `0` (overflowed from `9223372036854775808`)
911
}
1012

1113
fn main() {}

src/test/ui/enum/enum-discrim-autosizing.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0081]: discriminant value `0` already exists
44
LL | Au64 = 0,
55
| - first use of `0`
66
LL | Bu64 = 0x8000_0000_0000_0000
7-
| ^^^^^^^^^^^^^^^^^^^^^ enum already has `0`
7+
| ^^^^^^^^^^^^^^^^^^^^^ enum already has `0` (overflowed from `9223372036854775808`)
88

99
error: aborting due to previous error
1010

src/test/ui/error-codes/E0081.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
enum Enum {
22
P = 3,
3+
//~^ NOTE first use of `3`
34
X = 3,
45
//~^ ERROR discriminant value `3` already exists
6+
//~| NOTE enum already has `3`
57
Y = 5
68
}
79

10+
#[repr(u8)]
11+
enum EnumOverflowRepr {
12+
P = 257,
13+
//~^ NOTE first use of `1` (overflowed from `257`)
14+
X = 513,
15+
//~^ ERROR discriminant value `1` already exists
16+
//~| NOTE enum already has `1` (overflowed from `513`)
17+
}
18+
819
fn main() {
920
}

src/test/ui/error-codes/E0081.stderr

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
error[E0081]: discriminant value `3` already exists
2-
--> $DIR/E0081.rs:3:9
2+
--> $DIR/E0081.rs:4:9
33
|
44
LL | P = 3,
55
| - first use of `3`
6+
LL |
67
LL | X = 3,
78
| ^ enum already has `3`
89

9-
error: aborting due to previous error
10+
error[E0081]: discriminant value `1` already exists
11+
--> $DIR/E0081.rs:14:9
12+
|
13+
LL | P = 257,
14+
| --- first use of `1` (overflowed from `257`)
15+
LL |
16+
LL | X = 513,
17+
| ^^^ enum already has `1` (overflowed from `513`)
18+
19+
error: aborting due to 2 previous errors
1020

1121
For more information about this error, try `rustc --explain E0081`.

0 commit comments

Comments
 (0)