`@max` is clever

pub fn main() !void {
    const clock = std.Io.Clock;

    var threaded: std.Io.Threaded = .init_single_threaded;
    const io: std.Io = threaded.io();

    const now = try clock.real.now(io);
    const seed: u64 = @intCast(now.nanoseconds & ((1 << 64) - 1));
    var engine: std.Random.DefaultPrng = .init(seed);
    const random: std.Random = engine.random();

    const a: u8 = @max(0, random.int(i8));
    std.debug.print("{} {}\n", .{ a, @TypeOf(@max(0, random.int(i8))) });
}

const std = @import("std");

This snippet compiles fine and prints out a non-negative integer and u7.

2 Likes

But mind potential unexpected integer overflows downstream!

λ cat main.zig
const std = @import("std");

pub fn main() void {
    std.debug.print("{}", .{f(300)});
}

fn f(x: u16) u16 {
    return @min(200, x) + 100;
}
matklad@TigerMac ~/p/tb/work (matklad/say-no-to-code-bloat *)
λ ./zig/zig run main.zig
thread 7412206 panic: integer overflow
/Users/matklad/p/tb/work/main.zig:8:25: 0x10483ed4f in f (main)
    return @min(200, x) + 100;
                        ^
/Users/matklad/p/tb/work/main.zig:4:30: 0x10483ec57 in main (main)
    std.debug.print("{}", .{f(300)});
                             ^
/Users/matklad/p/tb/work/zig/lib/std/start.zig:651:22: 0x10483ebbf in main (main)
            root.main();
                     ^
???:?:?: 0x19812ab97 in ??? (???)
???:?:?: 0x0 in ??? (???)
fish: Unknown command: fish_job_summary
1 Like

The cat main.zig output looks broken.

1 Like

Oof. It’d be nice if that return @min(200, x) + 100 could propagate the result type to the operands of + so that it becomes equivalent to return @as(u16, @min(200, x)) + @as(u16, 100) (there’s probably issues with that suggestion that I haven’t considered).

EDIT: Removed the link to the PTR removal proposal, I think the issue would still exist even with it gone.

It’s unfortunate that Zig’s safety-checked integer arithmetic in combination with implicit, reader-invisible types makes it so easy to shoot yourself in the foot. I really hope that ranged integer types (allow integer types to be any range · Issue #3806 · ziglang/zig · GitHub) with implicit widening arithmetic and explicit narrowing will happen, it would eliminate an entire class of footgun.

3 Likes