# 0146 — `xx i < t` drops the int→float cast, emits a mixed-type compare > **RESOLVED.** `lowerBinaryOp` (src/ir/lower/expr.zig) now promotes the > comparison operands to the common type before emitting the compare: for the > ordering/equality arms, when the promoted type `ty` (from `arithResultType`) > is a float, each operand whose IR type differs is coerced via `coerceToType` > (SIToFP / FPExt). LLVM then receives same-typed operands and a well-formed > `fcmp`, instead of a mixed-type compare the verifier rejects. Regression > test: `examples/0189-types-int-float-compare-promote.sx`. ## Summary A comparison whose left operand is an *inline* int→float cast against a float right operand (`if xx i < t { ... }`, with `i : i32` and `t : f32`) does NOT coerce the integer to float. The backend emits the compare with mismatched operand types and LLVM module verification fails the whole build: ``` LLVM verification failed: Both operands to ICmp instruction are not of the same type! %icmp = icmp slt i32 %load4, float %load5 error: default build pipeline failed: ComptimeVmBail: comptime emit_object: object emission failed ``` The same shape with `==` and `>` produces the matching `icmp eq`/`icmp sgt` variants — it is the cast in the comparison operand that is lost, not a single operator. ## Minimal repro ```sx #import "modules/std.sx"; ceil_half :: (v: f32) -> i32 { t := v - 0.5; i : i32 = xx t; if xx i < t { // <-- icmp slt i32, float — cast dropped i += 1; } i } main :: () -> i32 { print("{}\n", ceil_half(2.3)); 0 } ``` `bash sx build` on this fails at object emission with the verifier error above. ## Expected `xx i` is an i32→f32 cast; the comparison should be a float compare (`fcmp`), i.e. the cast must materialize before the compare. The literal value is computed correctly at comptime — only the emitted compare is malformed. ## Workaround (documented, in use) Bind the cast to a typed float local first, then compare the local: ```sx i : i32 = xx t; fi : f32 = xx i; // materialize the cast into a typed local if fi < t { i += 1; } // float compare, both operands f32 — OK ``` This compiles and runs correctly. Applied in `doc/selection.sx` (`ceil_half` / `floor_half_excl`). ## Related A sibling symptom in the same function family: `sy := xx y + 0.5` (with `y : i32`, `0.5` a comptime float) infers `sy` as **f64/double**, so a later `sy >= lo` against an `f32 lo` emits `fcmp oge double, float`. Annotating the local explicitly (`sy : f32 = xx y + 0.5`) pins it to f32 and the compare matches. Likely the same missing-coercion root cause around mixed int/comptime-float expressions feeding a float local or a compare.