# 0164 — `if ` with no binding silently folds the has_value test to `true` ## Symptom Branching on an optional **without a binding** (`if opt { ... }`) takes the present-branch unconditionally for any optional whose LLVM representation is a struct (`?i64`, `?T`, `?f64`, …). The has_value flag is never read — the IR emits `br i1 true`. SILENT MISCOMPILE (no diagnostic, wrong runtime result). Pointer-sentinel optionals (`?cstring`, `?*T`, `?Closure`) are unaffected — they lower to a bare `ptr` and hit the correct `icmp` path. The `if opt |x| { ... }` *binding* form is also correct (it emits `optional_has_value`). Observed vs expected: the repro prints `present` for a null optional; expected `absent`. ## Reproduction ```sx #import "modules/std.sx"; check :: (n: ?i64) { if n { print("present\n"); } else { print("absent\n"); } } main :: () { a : ?i64 = null; b : ?i64 = 42; check(a); // prints "present" — WRONG, expected "absent" check(b); // prints "present" — correct } ``` Reproduces identically for function-return init, literal-`null` init, literal-value init, and param-passed optionals — universal, not init-path specific. ## Investigation prompt Two sites collude: - `src/ir/lower/control_flow.zig` (`lowerIfExpr`, ~lines 69–72) emits `optional_has_value` **only when `ie.binding_name != null`**. For a bindingless `if opt`, it passes `cond = opt_val` (the raw `{T,i1}` aggregate) straight to `condBr`. Fix: emit `optional_has_value` whenever the condition's resolved type is an optional, binding or not. - `src/backend/llvm/ops.zig` (`emitCondBr`, ~lines 2378–2383) has a catch-all `else`/struct arm that does `cond = LLVMConstInt(i1, 1, 0)` with the comment "Struct values are always truthy". This is exactly the REJECTED silent-fallback pattern (see CLAUDE.md). After the lowering fix, make this arm a LOUD bail (a non-i1, non-pointer condition reaching condBr is a compiler bug) rather than a silent `true`. Verify: the repro prints `absent` / `present`; check the IR no longer contains `br i1 true` for the optional condition. Add an `examples/optionals/09xx-if-optional-no-binding.sx` regression covering null and present `?i64`/`?T` without a binding, both branches.