Skip to content

Commit

Permalink
Rollup merge of #87166 - de-vri-es:show-discriminant-before-overflow,…
Browse files Browse the repository at this point in the history
… 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)
  • Loading branch information
GuillaumeGomez authored Aug 22, 2021
2 parents 2627db6 + 4c0ff4d commit 3b1e7b1
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 8 deletions.
27 changes: 24 additions & 3 deletions compiler/rustc_typeck/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1413,15 +1413,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);
Expand All @@ -1431,6 +1433,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,
Expand Down
6 changes: 4 additions & 2 deletions src/test/ui/enum/enum-discrim-autosizing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
2 changes: 1 addition & 1 deletion src/test/ui/enum/enum-discrim-autosizing.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
11 changes: 11 additions & 0 deletions src/test/ui/error-codes/E0081.rs
Original file line number Diff line number Diff line change
@@ -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() {
}
14 changes: 12 additions & 2 deletions src/test/ui/error-codes/E0081.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 3b1e7b1

Please sign in to comment.