From da133533ed1d16275a523aa09b06b1c459691f6a Mon Sep 17 00:00:00 2001 From: Jaiden Magnan Date: Wed, 14 Jan 2026 10:50:32 -0500 Subject: [PATCH 1/5] fix: more descriptive error message for enum to integer --- compiler/rustc_hir_typeck/src/cast.rs | 30 +++++++++++++++---- .../ui/cast/cast-enum-to-int-issue-151116.rs | 11 +++++++ .../cast/cast-enum-to-int-issue-151116.stderr | 14 +++++++++ 3 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 tests/ui/cast/cast-enum-to-int-issue-151116.rs create mode 100644 tests/ui/cast/cast-enum-to-int-issue-151116.stderr diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 93275f62dcc17..e1d9d7fe6e538 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -291,12 +291,32 @@ impl<'a, 'tcx> CastCheck<'tcx> { CastError::NeedViaThinPtr | CastError::NeedViaPtr => { let mut err = make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx); + if self.cast_ty.is_integral() { - err.help(format!("cast through {} first", match e { - CastError::NeedViaPtr => "a raw pointer", - CastError::NeedViaThinPtr => "a thin pointer", - e => unreachable!("control flow means we should never encounter a {e:?}"), - })); + if !matches!(self.expr.kind, ExprKind::AddrOf(..)) + && let ty::Ref(_, inner_ty, _) = *self.expr_ty.kind() + && let ty::Adt(adt_def, _) = *inner_ty.kind() + && adt_def.is_enum() + && adt_def.is_payloadfree() + { + err.span_suggestion_verbose( + self.expr_span.shrink_to_lo(), + "dereference the expression", + "*", + Applicability::MachineApplicable, + ); + } else { + err.help(format!( + "cast through {} first", + match e { + CastError::NeedViaPtr => "a raw pointer", + CastError::NeedViaThinPtr => "a thin pointer", + e => unreachable!( + "control flow means we should never encounter a {e:?}" + ), + } + )); + } } self.try_suggest_collection_to_bool(fcx, &mut err); diff --git a/tests/ui/cast/cast-enum-to-int-issue-151116.rs b/tests/ui/cast/cast-enum-to-int-issue-151116.rs new file mode 100644 index 0000000000000..ac6ff7b806edf --- /dev/null +++ b/tests/ui/cast/cast-enum-to-int-issue-151116.rs @@ -0,0 +1,11 @@ +#[repr(u8)] +enum Priority { + High = 255, + Normal = 127, + Low = 1, +} + +fn main() { + let priority = &Priority::Normal; + let priority = priority as u8; //~ ERROR casting `&Priority` as `u8` is invalid +} diff --git a/tests/ui/cast/cast-enum-to-int-issue-151116.stderr b/tests/ui/cast/cast-enum-to-int-issue-151116.stderr new file mode 100644 index 0000000000000..f1bcf3f26ea57 --- /dev/null +++ b/tests/ui/cast/cast-enum-to-int-issue-151116.stderr @@ -0,0 +1,14 @@ +error[E0606]: casting `&Priority` as `u8` is invalid + --> $DIR/cast-enum-to-int-issue-151116.rs:10:20 + | +LL | let priority = priority as u8; + | ^^^^^^^^^^^^^^ + | +help: dereference the expression + | +LL | let priority = *priority as u8; + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0606`. From 53f0ce84b2723ef508db374cdfdfddd07bcf477d Mon Sep 17 00:00:00 2001 From: Jaiden Magnan Date: Wed, 14 Jan 2026 11:32:24 -0500 Subject: [PATCH 2/5] fix: add the HELP message --- tests/ui/cast/cast-enum-to-int-issue-151116.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/cast/cast-enum-to-int-issue-151116.rs b/tests/ui/cast/cast-enum-to-int-issue-151116.rs index ac6ff7b806edf..2c278d61ec1c6 100644 --- a/tests/ui/cast/cast-enum-to-int-issue-151116.rs +++ b/tests/ui/cast/cast-enum-to-int-issue-151116.rs @@ -8,4 +8,5 @@ enum Priority { fn main() { let priority = &Priority::Normal; let priority = priority as u8; //~ ERROR casting `&Priority` as `u8` is invalid + //~| HELP: dereference the expression } From 9f43e6dafa23368feed921a3c4126126aaa9728e Mon Sep 17 00:00:00 2001 From: Jaiden Magnan Date: Sun, 26 Apr 2026 15:07:48 -0400 Subject: [PATCH 3/5] feat: fixing PR feedback --- compiler/rustc_hir_typeck/src/cast.rs | 2 +- tests/ui/cast/cast-enum-to-int-issue-151116.rs | 3 +++ tests/ui/cast/cast-enum-to-int-issue-151116.stderr | 10 +++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index e1d9d7fe6e538..77d45b46f1d7b 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -303,7 +303,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.expr_span.shrink_to_lo(), "dereference the expression", "*", - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } else { err.help(format!( diff --git a/tests/ui/cast/cast-enum-to-int-issue-151116.rs b/tests/ui/cast/cast-enum-to-int-issue-151116.rs index 2c278d61ec1c6..d254b6400f2d4 100644 --- a/tests/ui/cast/cast-enum-to-int-issue-151116.rs +++ b/tests/ui/cast/cast-enum-to-int-issue-151116.rs @@ -9,4 +9,7 @@ fn main() { let priority = &Priority::Normal; let priority = priority as u8; //~ ERROR casting `&Priority` as `u8` is invalid //~| HELP: dereference the expression + + let priority = &Priority::Normal as u8; //~ ERROR casting `&Priority` as `u8` is invalid + //~| HELP: cast through a raw pointer first } diff --git a/tests/ui/cast/cast-enum-to-int-issue-151116.stderr b/tests/ui/cast/cast-enum-to-int-issue-151116.stderr index f1bcf3f26ea57..63a4a0cb71881 100644 --- a/tests/ui/cast/cast-enum-to-int-issue-151116.stderr +++ b/tests/ui/cast/cast-enum-to-int-issue-151116.stderr @@ -9,6 +9,14 @@ help: dereference the expression LL | let priority = *priority as u8; | + -error: aborting due to 1 previous error +error[E0606]: casting `&Priority` as `u8` is invalid + --> $DIR/cast-enum-to-int-issue-151116.rs:13:20 + | +LL | let priority = &Priority::Normal as u8; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: cast through a raw pointer first + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0606`. From 61743bf3b0ae0f9ea00c16ba742899739be2e55a Mon Sep 17 00:00:00 2001 From: Jaiden Magnan Date: Tue, 5 May 2026 16:19:41 -0400 Subject: [PATCH 4/5] fix: adding more verbose error message --- compiler/rustc_hir_typeck/src/cast.rs | 10 +++++++++- tests/ui/cast/cast-enum-to-int-issue-151116.rs | 4 ++-- tests/ui/cast/cast-enum-to-int-issue-151116.stderr | 7 ++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 77d45b46f1d7b..40315e8270e12 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -301,10 +301,18 @@ impl<'a, 'tcx> CastCheck<'tcx> { { err.span_suggestion_verbose( self.expr_span.shrink_to_lo(), - "dereference the expression", + "try dereferencing before the cast", "*", Applicability::MaybeIncorrect, ); + if !fcx.type_is_copy_modulo_regions(fcx.param_env, inner_ty) { + err.span_suggestion_verbose( + fcx.tcx.def_span(adt_def.did()).shrink_to_lo(), + "add `#[derive(Copy, Clone)]` to the enum definition", + "#[derive(Copy, Clone)]\n", + Applicability::MaybeIncorrect, + ); + } } else { err.help(format!( "cast through {} first", diff --git a/tests/ui/cast/cast-enum-to-int-issue-151116.rs b/tests/ui/cast/cast-enum-to-int-issue-151116.rs index d254b6400f2d4..25a85e10a83e5 100644 --- a/tests/ui/cast/cast-enum-to-int-issue-151116.rs +++ b/tests/ui/cast/cast-enum-to-int-issue-151116.rs @@ -1,5 +1,5 @@ #[repr(u8)] -enum Priority { +enum Priority { //~ HELP: add `#[derive(Copy, Clone)]` to the enum definition High = 255, Normal = 127, Low = 1, @@ -8,7 +8,7 @@ enum Priority { fn main() { let priority = &Priority::Normal; let priority = priority as u8; //~ ERROR casting `&Priority` as `u8` is invalid - //~| HELP: dereference the expression + //~| HELP: try dereferencing before the cast let priority = &Priority::Normal as u8; //~ ERROR casting `&Priority` as `u8` is invalid //~| HELP: cast through a raw pointer first diff --git a/tests/ui/cast/cast-enum-to-int-issue-151116.stderr b/tests/ui/cast/cast-enum-to-int-issue-151116.stderr index 63a4a0cb71881..7eb0d357fb0de 100644 --- a/tests/ui/cast/cast-enum-to-int-issue-151116.stderr +++ b/tests/ui/cast/cast-enum-to-int-issue-151116.stderr @@ -4,10 +4,15 @@ error[E0606]: casting `&Priority` as `u8` is invalid LL | let priority = priority as u8; | ^^^^^^^^^^^^^^ | -help: dereference the expression +help: try dereferencing before the cast | LL | let priority = *priority as u8; | + +help: add `#[derive(Copy, Clone)]` to the enum definition + | +LL + #[derive(Copy, Clone)] +LL | enum Priority { + | error[E0606]: casting `&Priority` as `u8` is invalid --> $DIR/cast-enum-to-int-issue-151116.rs:13:20 From 0f5d89fea1d8751a94e2e023959743da7516dc80 Mon Sep 17 00:00:00 2001 From: Jaiden Magnan Date: Tue, 5 May 2026 17:34:50 -0400 Subject: [PATCH 5/5] fix: CopyPriority addition --- tests/ui/cast/cast-enum-to-int-issue-151116.rs | 12 ++++++++++++ .../cast/cast-enum-to-int-issue-151116.stderr | 17 ++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/tests/ui/cast/cast-enum-to-int-issue-151116.rs b/tests/ui/cast/cast-enum-to-int-issue-151116.rs index 25a85e10a83e5..26da80bcf2774 100644 --- a/tests/ui/cast/cast-enum-to-int-issue-151116.rs +++ b/tests/ui/cast/cast-enum-to-int-issue-151116.rs @@ -5,6 +5,14 @@ enum Priority { //~ HELP: add `#[derive(Copy, Clone)]` to the enum definition Low = 1, } +#[repr(u8)] +#[derive(Copy, Clone)] +enum CopyPriority { + High = 255, + Normal = 127, + Low = 1, +} + fn main() { let priority = &Priority::Normal; let priority = priority as u8; //~ ERROR casting `&Priority` as `u8` is invalid @@ -12,4 +20,8 @@ fn main() { let priority = &Priority::Normal as u8; //~ ERROR casting `&Priority` as `u8` is invalid //~| HELP: cast through a raw pointer first + + let priority = &CopyPriority::Normal; + let priority = priority as u8; //~ ERROR casting `&CopyPriority` as `u8` is invalid + //~| HELP: try dereferencing before the cast } diff --git a/tests/ui/cast/cast-enum-to-int-issue-151116.stderr b/tests/ui/cast/cast-enum-to-int-issue-151116.stderr index 7eb0d357fb0de..63baef70585de 100644 --- a/tests/ui/cast/cast-enum-to-int-issue-151116.stderr +++ b/tests/ui/cast/cast-enum-to-int-issue-151116.stderr @@ -1,5 +1,5 @@ error[E0606]: casting `&Priority` as `u8` is invalid - --> $DIR/cast-enum-to-int-issue-151116.rs:10:20 + --> $DIR/cast-enum-to-int-issue-151116.rs:18:20 | LL | let priority = priority as u8; | ^^^^^^^^^^^^^^ @@ -15,13 +15,24 @@ LL | enum Priority { | error[E0606]: casting `&Priority` as `u8` is invalid - --> $DIR/cast-enum-to-int-issue-151116.rs:13:20 + --> $DIR/cast-enum-to-int-issue-151116.rs:21:20 | LL | let priority = &Priority::Normal as u8; | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: cast through a raw pointer first -error: aborting due to 2 previous errors +error[E0606]: casting `&CopyPriority` as `u8` is invalid + --> $DIR/cast-enum-to-int-issue-151116.rs:25:20 + | +LL | let priority = priority as u8; + | ^^^^^^^^^^^^^^ + | +help: try dereferencing before the cast + | +LL | let priority = *priority as u8; + | + + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0606`.