enforce integer division via explicit builtins

This commit is contained in:
2026-07-13 11:39:06 +02:00
parent a4d0fb1e26
commit 2ed333c70d
13 changed files with 1004 additions and 98 deletions
+22 -9
View File
@@ -116,7 +116,7 @@
- `for 0..(len) |i| { ... }` or equivalently `for 0..=(len - 1) |i| { ... }` - calculating range bounds, expressions must be parenthesized
- for all conditionals/guards, parentheses are optional but allowed for visual clarity
6. compound assignment: `+=`, `-=`, `*=`, `/=` (implemented)
6. compound assignment: `+=`, `-=`, `*=`, `/=` (implemented; division semantics superseded by milestone 32)
- added the binary arithmetic operators `-`, `*`, `/` (previously only `+` existed); `*`/`/`
bind tighter than `+`/`-`, and prefix `-` (negation) is unchanged
- compound assignments preserve the target, operator, and right-hand side explicitly through
@@ -124,10 +124,9 @@
operation, and stores through that address
- side-effecting index, field-base, and dereference expressions are evaluated once in
left-to-right order
- integer arithmetic traps on overflow (`Sub_Checked`/`Mul_Checked` via the LLVM
`.with.overflow` intrinsics) and integer `/` traps on divide-by-zero and `INT_MIN / -1`;
floats follow IEEE (`fadd`/`fsub`/`fmul`/`fdiv`, no trap)
- constant folding (global initializers) covers `-`, `*`, `/` alongside `+`
- integer `+`, `-`, and `*` trap on overflow; milestone 32 later restricted `/` and `/=` to
floats and introduced the explicit integer/float division family
- constant folding (global initializers) covers the arithmetic family
7. enums (native and c interop) (implemented; see below)
- native enums are nominal value types with integer runtime representations
@@ -791,10 +790,24 @@
- the existing specialization/HIR/LLVM ABI is unchanged; `std/mem` and `std/arraylist` now use the
inferred form where their arguments or result provide enough information
32. disallow arbitrary integer division
- take inspiration from zig
- see also below for a word on unchecked casts
- the user should be explicit about what they mean with integer division (e.g. `div`, `rem`)
32. explicit division family (implemented)
- `/` and `/=` are float-only; every integer use is rejected with guidance toward explicit
division, including literals, comptime execution, array counts, and compound assignment
- direct unqualified calls reserve `div_trunc`, `div_floor`, `div_exact`, `div_ceil`, `rem`, and
`mod`; qualified names remain ordinary package functions
- the builtins accept compatible concrete integer or float scalars, reuse existing literal and
widening rules, and return the common operand type (integral-valued floats for quotients)
- all builtins diagnose zero denominators at comptime and trap at runtime; quotient operations
also trap on signed `min_value(T) / -1`, while `rem` and `mod` return zero for that pair
- `div_exact` checks the reconstructed dividend in the operand type; `rem` pairs with truncation
and follows the numerator sign, while `mod` pairs with floor and follows the denominator sign
- HIR/IR use compact semantic enum tags; integer floor, ceil, and exact lowering reconstructs the
remainder from one quotient so each produces only one hardware-division candidate
- float lowering uses the typed LLVM trunc/floor/ceil intrinsics, `frem`, and ordered equality;
ordinary float `/` remains the unchecked IEEE infinity/NaN escape hatch
- migrated `std/mem`, `std/arraylist`, and the compound-assignment example to `div_trunc`
33. design io interface
## A word on unchecked casts