Skip to content

Inconsistent shift behavior when shifting by 32 #83

@Hugobros3

Description

@Hugobros3

While trying to isolate other issues I'm having with Impla (it randomly segfaults when building my bvh builder, will make another issue once I narrow down the problem), I found out the shift right behavior is inconsistent when shifting a 32-bit value by 32 places to the right. One would expect that to produce a zero, and that was what my logic assumed, but I know this is undefined behavior in some languages. Trick is, here it's undefined behavior depending on context, which is extra gnarly. I managed to isolate three cases:

  • The result of such a shift is 1, the default case in an empty example
  • The result of such a shift is zero, if you have an indefinite array initialized before
  • The result is the original number, untouched, if the 32 value is obtained at runtime (here with an extern C function)

The issue is here no matter if signed or unsigned values are used

extern "C" {
    fn unknown_at_compile_time_but_its_32_really() -> i32;
}

extern fn buggy_shift() -> () {
    //let uncomment_this_and_the_result_is_zero = ~[1:i32];

    // uncomment that and the result is 507
    //let shift_by = unknown_at_compile_time_but_its_32_really();
    let shift_by = 32;

    print_value(shift_by, "shifting by...");

    fn @shift(i: i32) -> i32 {
        i >> shift_by as i32
    }

    fn @shift_unsigned(i: u32) -> u32 {
        i >> (shift_by as u32)
    }

    print_value(shift(507),"result");
    print_value(shift_unsigned(507_u32) as i32,"result for unsigned");
}

I believe this is not actually meant to be undefined behavior, and/or should be documented clearly (I lost quite a bit of time to this).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions