fix(0112): out-of-range int literals error instead of silently wrapping
checkIntLiteralFits range-checks a literal against its integer target (builtins + custom widths via intLiteralRange; width-64 types skip — every representable literal is a legal bit pattern there) and diagnoses with the type's range and an xx/cast hint. Wired into the .int_literal arm (covers decls, assignments, call args, struct-literal fields), lowerStructConstant, and globalInitValue. A negated literal now folds to a single constant so -128 range-checks as -128 rather than as an out-of-range +128 intermediate. An explicit xx operand skips the check — truncation stays available on request (cast(T) was already exempt: its value arg lowers without the target). examples/0300-closures-lambda.sx pinned 133 wrapping to -3 through an s3 param — the exact class this outlaws; updated to a fitting value. Found during the fix and filed separately: issue 0113 (negated-literal global initializers rejected as non-constant; pre-existing). Regressions: examples/1156-diagnostics-int-literal-out-of-range.sx, examples/0174-types-int-literal-boundaries.sx.
This commit is contained in:
@@ -1,3 +1,35 @@
|
||||
# RESOLVED — 0112: out-of-range int literal silently wraps into a narrower annotated target
|
||||
|
||||
**Root cause:** the `.int_literal` arm adopted an integer `target_type` with no
|
||||
fits-check, truncating at emission width; `globalInitValue` serialized literal
|
||||
global initializers raw the same way.
|
||||
|
||||
**Fix:** `Lowering.checkIntLiteralFits` (src/ir/lower.zig) range-checks a
|
||||
literal against its integer target (`intLiteralRange`: builtins + custom
|
||||
widths; width-64 types skip — every representable literal is legal there) and
|
||||
diagnoses `integer literal N does not fit in T (range lo..hi) — use an
|
||||
explicit `xx` / `cast` to truncate`. Wired into the `.int_literal` arm,
|
||||
`lowerStructConstant`, and `globalInitValue`. A negated literal now folds to
|
||||
one constant (`-128` checks as -128, not as an out-of-range +128
|
||||
intermediate), and an explicit `xx` operand skips the check
|
||||
(`suppress_int_fit_check`) — truncation stays available on request;
|
||||
`cast(T)` was already exempt (its value arg lowers without the target).
|
||||
Coverage via the shared arm: decls, assignments, call args, struct-literal
|
||||
fields, struct constants, globals.
|
||||
|
||||
**Behavior change:** `examples/0300-closures-lambda.sx` passed `133` to an
|
||||
`s3` param and pinned the wrapped `-3`; updated to a fitting value.
|
||||
|
||||
**Regression tests:** `examples/1156-diagnostics-int-literal-out-of-range.sx`
|
||||
(both faces diagnosed in one run) and
|
||||
`examples/0174-types-int-literal-boundaries.sx` (extreme in-range values,
|
||||
width-64 types, `xx`/`cast` escapes, call args).
|
||||
|
||||
**Found during the fix:** negated-literal GLOBAL initializers (`g : s64 = -1;`)
|
||||
are rejected as non-constant — pre-existing gap, filed as issue 0113.
|
||||
|
||||
---
|
||||
|
||||
# 0112 — out-of-range int literal silently wraps into a narrower annotated target
|
||||
|
||||
**Symptom.** An integer literal that does not fit its explicitly-annotated
|
||||
|
||||
Reference in New Issue
Block a user