fix: bindingless if/while/and/or over optional reads has_value (issue 0164)
lowerIfExpr emitted optional_has_value only for the binding form; a bare
'if opt' passed the raw {T,i1} aggregate to condBr, where emitCondBr's
catch-all struct arm silently folded it to 'i1 true' (structs always
truthy) — a silent miscompile that took the present-branch for null
optionals. while / and / or shared the same defect.
Reduce bindingless optional conditions to optional_has_value in
lowerIfExpr/lowerWhile and via a new lowerBoolCondition helper for and/or
operands. Replace the silent-true emitCondBr arm with a lowering-time
diagnostic (checkConditionType/isValidConditionType) rejecting conditions
whose type isn't bool/integer/pointer/optional; the backend @panic is now
an unreachable tripwire.
Regressions: examples/optionals/0908..0910 + diagnostics/1194 (negative).
Verified by 3+3 adversarial reviews.
Filed adjacent bugs found during review: 0168 (array-of-optionals element
load), 0169 (optional->bool coercion), 0170 (closure-optional layout).
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
// A branch condition (`if` / `while` / `and` / `or`) must reduce to an i1:
|
||||
// its type must be a bool, integer, pointer, or optional. A struct (or float,
|
||||
// etc.) has no truthiness — it used to be silently folded truthy at lowering
|
||||
// then `@panic` in the LLVM backend (issue 0164). It must instead be a clean,
|
||||
// located compile-time TYPE error.
|
||||
//
|
||||
// Negative test: locks the new diagnostic. `if <struct>` is rejected.
|
||||
#import "modules/std.sx";
|
||||
|
||||
S :: struct { x: i64; }
|
||||
|
||||
main :: () -> i64 {
|
||||
s : S = .{ x = 1 };
|
||||
if s { return 1; } // ERROR: condition must be a bool, integer, pointer, or optional
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: condition must be a bool, integer, pointer, or optional, but has type 'S'
|
||||
--> examples/diagnostics/1194-diagnostics-condition-non-bool-type.sx:14:8
|
||||
|
|
||||
14 | if s { return 1; } // ERROR: condition must be a bool, integer, pointer, or optional
|
||||
| ^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user