Skip to content

constant: correctly handle signedness in const_to_opt_u128.#558

Draft
eddyb wants to merge 1 commit intomainfrom
eddyb/const_to_opt_u128-sign_ext
Draft

constant: correctly handle signedness in const_to_opt_u128.#558
eddyb wants to merge 1 commit intomainfrom
eddyb/const_to_opt_u128-sign_ext

Conversation

@eddyb
Copy link
Copy Markdown
Member

@eddyb eddyb commented Apr 13, 2026

One of the more insidious bugs found via Rustlantis (using a sample from @FractalFir's Rust-GPU port of it).

const_to_opt_u128 is used by rustc_codegen_ssa to optimize switchInt on the fly (i.e. replacing match CONST {...} with an unconditional branch to one of its cases), and that was working fine for unsigned discriminants, but we were wrong for signed ones, due to MIR storing switchInt cases as zero-extended-to-u128 (e.g. -1i8 => ... becomes 255 => ...).

More specifically, when const_to_opt_u128(x, /*sign_ext*/ false) was called with x of a signed integer type, we were wrongly sign-extending (based on type) instead of zero-extending (based on sign_ext == false).


TODO: still needs a test, perhaps something along the lines of:

#[inline(never)]
fn const_i32_is_neg1<const X: i32>() -> bool {
    match X {
        -1 => true,
        _ => false,
    }
}

fn main() {
    assert!(const_i32_is_neg1::<-1>());
}

(you can see the lack of a switch in the LLVM IR: https://godbolt.org/z/hj6WEKj3v)
(also, unrelatedly, that godbolt sample made me notice 1.94 -> 1.95-beta generates more unnecessary LLVM IR in some situations, and nightly still does, too)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant