Why does Zig allow comptime_float coercion to ints when fractional part is 0?

// This code compiles, prints 12
fn f1() void {
    var a: u8 = 10.0;
    a += 2.0;
    print("{}", .{a});
    return 0;
}

// This code does not compile
fn f2() void {
    var a: u8 = 10.0;
    a += 2.1;
    print("{}", .{a});
    return 0;
}

I understand that Zig does not allow 2.1 to be coerced to u8 in f2. What I don’t understand is why it’s allowed allows comptime_float to be coerced to a u8 in f1, as long as that float does not have a fractional part.

What is the reasoning to allow this?

Rust for example does not allow it.

  1. Rust does not have comptime values.
  2. Why not?
5 Likes

At compile time Zig will allow any numeric coercion to happen as long as the value fits the target type without losing precision, here are 2 more examples:

const x: f32 = 16.0;
// Here sqrt complained that it cannot work with usize result type
// using floats is the only way to square-root an integer at compile time.
const y: usize = @as(f32, @sqrt(x)); 
const z: i32 = y;
@compileLog(z); // 4

Often this reduces friction since you don’t need to worry about additional casts.

6 Likes

Wow, cool!

This clears it up: there is in fact a solid rule that is being used

1 Like

Good point regarding Rust: the compiler does consider all floating point literals to be f64 unless they are explicitly typed or inferred. So that comparison was admittedly useless, sorry.

Regarding your “Why not” point, what I meant was: “Why allow this sort of exception, where x.0 is allowed to be cast into integers, but x.1 is not? What’s the rule that is being followed?”. @IntegratedQuantum ‘s response clears it up perfectly! Zig will always allow cast from one numeric type to another, as long as this cast can happen without precision loss!

1 Like

This only applies to comptime arithmetic. (Your reply reads as if perhaps you missed that). Zig certainly won’t perform such casts on runtime values; you’ll get a compile error instead. If you’re running this in a test function, try declaring your float as var instead of const and see what happens.

1 Like

Alright, thanks :slight_smile:

1 Like