Skip to content

Commit 3b1e7b1

Browse files
Rollup merge of #87166 - de-vri-es:show-discriminant-before-overflow, r=jackh726
Show discriminant before overflow in diagnostic for duplicate values. This PR adds the value before overflow for explicit discriminant values in the error for duplicate discriminant values. I found it rather confusing to see only the overflowed value. It only does this for literals, since overflows in const evaluated arithmetic are already a hard error. This is my first PR to the compiler, so please let me know if the implementation can be improved :) Before: ![image](https://user-images.githubusercontent.com/786213/125850097-bf5fb7e0-d800-4386-a738-c30f41822964.png) After: ![image](https://user-images.githubusercontent.com/786213/125850120-e2bb765d-ad86-4888-a6cb-dec34fba3fea.png)
2 parents 2627db6 + 4c0ff4d commit 3b1e7b1

File tree

5 files changed

+52
-8
lines changed

5 files changed

+52
-8
lines changed

compiler/rustc_typeck/src/check/check.rs

+24-3
Original file line numberDiff line numberDiff line change
@@ -1413,15 +1413,17 @@ fn check_enum<'tcx>(
14131413
Some(ref expr) => tcx.hir().span(expr.hir_id),
14141414
None => v.span,
14151415
};
1416+
let display_discr = display_discriminant_value(tcx, v, discr.val);
1417+
let display_discr_i = display_discriminant_value(tcx, variant_i, disr_vals[i].val);
14161418
struct_span_err!(
14171419
tcx.sess,
14181420
span,
14191421
E0081,
14201422
"discriminant value `{}` already exists",
1421-
disr_vals[i]
1423+
discr.val,
14221424
)
1423-
.span_label(i_span, format!("first use of `{}`", disr_vals[i]))
1424-
.span_label(span, format!("enum already has `{}`", disr_vals[i]))
1425+
.span_label(i_span, format!("first use of {}", display_discr_i))
1426+
.span_label(span, format!("enum already has {}", display_discr))
14251427
.emit();
14261428
}
14271429
disr_vals.push(discr);
@@ -1431,6 +1433,25 @@ fn check_enum<'tcx>(
14311433
check_transparent(tcx, sp, def);
14321434
}
14331435

1436+
/// Format an enum discriminant value for use in a diagnostic message.
1437+
fn display_discriminant_value<'tcx>(
1438+
tcx: TyCtxt<'tcx>,
1439+
variant: &hir::Variant<'_>,
1440+
evaluated: u128,
1441+
) -> String {
1442+
if let Some(expr) = &variant.disr_expr {
1443+
let body = &tcx.hir().body(expr.body).value;
1444+
if let hir::ExprKind::Lit(lit) = &body.kind {
1445+
if let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node {
1446+
if evaluated != *lit_value {
1447+
return format!("`{}` (overflowed from `{}`)", evaluated, lit_value);
1448+
}
1449+
}
1450+
}
1451+
}
1452+
format!("`{}`", evaluated)
1453+
}
1454+
14341455
pub(super) fn check_type_params_are_used<'tcx>(
14351456
tcx: TyCtxt<'tcx>,
14361457
generics: &ty::Generics,

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

+4-2
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

+1-1
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

+11
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

+12-2
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)