Skip to content

fix: const eval cast of single-variant enum - #23185

Open
hlsxx wants to merge 1 commit into
rust-lang:masterfrom
hlsxx:enum-dicr-evaluation
Open

fix: const eval cast of single-variant enum#23185
hlsxx wants to merge 1 commit into
rust-lang:masterfrom
hlsxx:enum-dicr-evaluation

Conversation

@hlsxx

@hlsxx hlsxx commented Aug 18, 2026

Copy link
Copy Markdown

Single-variant enum incorrectly evaluated to 0.

Previously enum-to-int casts were lowered as a plain Rvalue::Cast, causing single-variant enums to evaluate to 0 instead of their corresponding discriminant value.

Fixes enum discriminant handling in MIR lowering by extracting the discriminant before performing the integer cast. Prevents recursion in MIR evaluation by reading discriminant bytes directly when the owner is a variant of the same enum in Rvalue::Discriminant branch.

Fixes #23148

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 18, 2026

@ChayimFriedman2 ChayimFriedman2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't the correct way to fix that. It should be fixed during MIR lowering, see the corresponding code in rustc: https://github.com/rust-lang/rust/blob/e71c0f1e3395b10a8c331317be1a5c107bdf7b2e/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs#L125-L163.

View changes since this review

@hlsxx
hlsxx force-pushed the enum-dicr-evaluation branch from 6e61250 to 5627c1c Compare August 28, 2026 16:44
@rustbot

rustbot commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@hlsxx
hlsxx force-pushed the enum-dicr-evaluation branch 2 times, most recently from d50b7b5 to b36d82e Compare August 28, 2026 16:51
@hlsxx
hlsxx force-pushed the enum-dicr-evaluation branch from b36d82e to b32e18a Compare August 29, 2026 10:37
@hlsxx
hlsxx requested a review from ChayimFriedman2 August 29, 2026 10:54
let ty = self.place_ty(p, locals)?;
let bytes = self.eval_place(p, locals)?.get(self)?;
let result = self.compute_discriminant(ty, bytes)?;
let result = if let Some(f) = locals.body.owner.as_variant()

@ChayimFriedman2 ChayimFriedman2 Sep 2, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I said you do not need to change eval. Why are you doing it?

View changes since the review

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I've tried to understand how it works and how it should be solved. I made the eval changes because the updated lower changes introduce Rvalue::Discriminant in the cast path. Then one of the enums test was failing with RecursiveTypeWithoutIndirection when evaluating discriminant layout for enums with self-referencing expressions.

So, the eval change was basically workaround for that. I'll try to look into a better approach that keeps the fix contained in specifically in lower.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The eval change is not correct. If you point me at the failing test and provide the full error, I could maybe assist with it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without the eval changes tests fail at https://github.com/rust-lang/rust-analyzer/blob/master/crates/hir-ty/src/consteval/tests.rs#L2494.

failures:

---- consteval::tests::enums stdout ----

thread 'consteval::tests::enums' (29899) panicked at crates/hir-ty/src/consteval/tests.rs:97:17:
Error in evaluating goal: Mir eval error:
Layout for type `E` is not available due RecursiveTypeWithoutIndirection
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

failures:
    consteval::tests::enums

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I discovered the cause: when computing the discriminant we need to compute the enum's layout which compute all discriminants, creating a cycle. The question is why it doesn't happen in rustc, I'll keep investigating.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see: rustc has specific logic for that in THIR lowering (which you should replicate in MIR lowering). See:

https://github.com/rust-lang/rust/blob/a69a63265cfd9e006d43137f98301b8d274ad4c9/compiler/rustc_mir_build/src/thir/cx/expr.rs#L325-L380

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FP expected [i32; 0], found [i32; 4] wrong array size infer

3 participants