Language
·
v0.0.13
Operators and arithmetic
Default arithmetic: checked in debug, wraps in release
let a: i32 = 10 + 20;
let c: i32 = 10 / 3; // 3
let d: i32 = 10 % 3; // 1
let e: i32 = 10 - 20; // -10
Default arithmetic is overflow-checked in debug builds and wraps in release. Division by zero always traps, in both modes.
Wrapping operators: always wrap
When you genuinely want wrap-on-overflow, use the %-suffixed family. They make the intent explicit, because silent overflow is a footgun you should opt into:
let a: u8 = 250u8 +% 10u8; // 4
let b: i8 = 100i8 *% 3i8; // overflows, wraps silently
let c: i32 = 0 -% 1; // -1, the canonical "this can underflow" idiom
Bitwise and shifts
let h: i32 = 0xff & 0x0f; // 15
let i: i32 = 0xf0 | 0x0f; // 255
let j: i32 = 0xff ^ 0xaa; // 85
let k: i32 = 1 << 8; // 256
let l: i32 = 256 >> 2; // 64
let m: u32 = ~(0 as u32); // 0xffffffff
Right shift on a signed type is arithmetic (sign-preserving); on an unsigned type it is logical (zero-fill).
Byte-swap intrinsics
let port_be: u16 = htons(8080 as u16);
let n: u32 = bswap32(0x12345678 as u32);
htons / htonl convert host order to network order. bswap16 / bswap32 / bswap64 are unconditional swaps.
Comparisons
let lt: bool = a < b;
let eq: bool = a == b; // no coercion
let ne: bool = a != b;
Casts: every width change is explicit
let x: i64 = 5;
let y: i32 = x as i32;
let f: f64 = (x as f64);
let z: usize = 10 as usize;
There is no int to bool, and no silent narrowing. A pointer and an integer convert only through usize, never through i32.