fix: reject implicit ?T -> bool coercion instead of silent false (issue 0169)
The Optional->Concrete unwrap classify rule treated ?i64 -> bool as unwrap+narrow (both builtin), silently yielding false for every optional (present or null). specs.md defines no implicit optional->bool conversion. Reject it: conversions.zig adds an optional_to_bool_reject plan (dst == bool, child != bool); coerce.zig emits a located diagnostic suggesting '!= null'. Covers arg/field-init/return via the shared coerceMode. The if-opt presence test (issue 0164) is a separate path, untouched. Regression: examples/diagnostics/1199-diagnostics-optional-to-bool.sx + conversions.test.zig unit test. Verified by 3 adversarial reviews, suite 789/0. Filed adjacent issue 0179 (whole implicit ?T->concrete unwrap family silently miscompiles a null optional; design-touching).
This commit is contained in:
@@ -1,5 +1,22 @@
|
||||
# 0169 — optional passed where `bool` is expected silently coerces to `false` (always)
|
||||
|
||||
> **RESOLVED** (scoped to `?T → bool`, `T ≠ bool`). The "Optional → Concrete
|
||||
> unwrap" classify rule treated `?i64 → bool` as unwrap+narrow (both i64 and bool
|
||||
> are builtin), silently yielding `false`. specs.md defines no implicit
|
||||
> optional→bool conversion, so the fix REJECTS it: `src/ir/conversions.zig` adds
|
||||
> an `optional_to_bool_reject` plan (when `dst == bool` and `child ≠ bool`);
|
||||
> `src/ir/lower/coerce.zig` emits a located diagnostic ("…use '!= null'…")
|
||||
> instead of a constant false. Covers arg / field-init / return (all share
|
||||
> `coerceMode`). `if opt` presence-test (issue 0164) is a separate path,
|
||||
> untouched. Verified by 3 adversarial reviews; suite 789/0. Regression:
|
||||
> `examples/diagnostics/1199-diagnostics-optional-to-bool.sx` + a
|
||||
> `conversions.test.zig` unit test. NOTE: review surfaced a larger sibling
|
||||
> surface — the whole implicit `?T → concrete` unwrap family (incl. the
|
||||
> `?bool → bool` cell still allowed here) silently miscompiles a NULL optional to
|
||||
> garbage — filed as **0179** (design-touching: needs the flow-narrowing
|
||||
> decision).
|
||||
|
||||
|
||||
## Symptom
|
||||
|
||||
Passing an optional (`?T`) to a `bool` parameter (or any bool-typed position:
|
||||
|
||||
Reference in New Issue
Block a user