Operators, Overflow and Casting

6.1 Operators

+ - * / % (integer / requires known-positive operands or @divTrunc/@divFloor/@divExact for signed values) +% -% *% (two's complement wrap) +| -| *| <<| (clamp to min/max) and or ! (short-circuit) orelse, .? catch, try, || (merge error sets)

++ (concatenation, comptime), ` (repetition, comptime) No operator overloading.** a + b` always means numeric addition.

No ++/-- increment operators. Use x += 1.

6.2 Integer Overflow

var a: u8 = 255;
// a += 1;                     // Debug/ReleaseSafe: panic "integer overflow"
a +%= 1;                       // wraps to 0
var b: u8 = 250;
b +|= 10;                      // saturates at 255
const res = @addWithOverflow(@as(u8, 200), 100);   // tuple { result, overflow_bit }
std.debug.print("{d} {d}\n", .{ res[0], res[1] });  // 44 1
// also @subWithOverflow, @mulWithOverflow, @shlWithOverflow
// std.math.add(u8, a, b) returns error.Overflow

6.3 Division

const x: i32 = -7;
_ = @divTrunc(x, 2);   // -3
_ = @divFloor(x, 2);   // -4
_ = @divExact(8, 2);   // 4 (UB if not exact; checked in safe modes)
_ = @rem(x, 2);        // -1
_ = @mod(x, 2);        // 1

6.4 Type Coercion and Casting

Implicit coercion is only allowed when it's lossless and safe: u8 → u16, i8 → i16, comptime_int → any integer that fits, *T → ?*T, [N]T pointer → slice, T → ?T, T → E!T, etc.

Since 0.11, cast builtins infer their result type from context. Use @as(T, @intCast(x)) when there's no context.

const small: u8 = 200;
const big: u32 = small;                   // OK: widening
const explicit = @as(u16, small);         // @as: explicit, safe coercion
const narrowed: u8 = @intCast(big);       // checked narrowing (panics in safe modes if it doesn't fit)
const truncated: u8 = @truncate(@as(u32, 0x1234));   // 0x34 (discard high bits)
const f: f32 = @floatFromInt(big);
const i: i32 = @intFromFloat(3.99);       // 3 (UB if out of range)
const fl: f32 = @floatCast(@as(f64, 1.5));
const bits: u32 = @bitCast(@as(f32, 1.0));   // reinterpret bits
const e: u8 = @intFromEnum(Color.red);
const c: Color = @enumFromInt(1);
const b: u1 = @intFromBool(true);