# 0066 — match-as-value with a negated-literal arm builds a mismatched phi > **RESOLVED.** `lowerMatch`'s value path (`has_value_merge`) now lowers each > arm body with `target_type = result_type`, so literals and negated literals in > the arms pick the merge's width instead of leaking a narrower one. The phi > operands are uniform; `coerceToType` still runs afterward as a backstop. > Regression: `examples/0043-basic-match-value-mixed-width.sx`. ## Symptom A value-position `match` (the `if subject == { case ... }` sugar) returning a small integer type, where one arm is a **negated integer literal** (`-1`) and others are plain positive literals, fails LLVM verification: ``` LLVM verification failed: PHI node operands are not the same type as the result! %bp = phi i64 [ 100, %match.arm.1 ], [ 10, %match.arm.2 ], [ -1, %match.arm.3 ] ``` The negated arm lowers its value at a different integer width (it emits an i32 that is then sign-extended) than the positive-literal arms (i64), so the merge phi's operands disagree with its result type. Positive literals in every arm work; `if/else` with `-1` works. So it is specific to a **negated literal in a match arm value**. This is orthogonal to the trailing-`;` block-value rule — the repro uses the exempt `case …: expr;` arm form (unchanged by that migration) and reproduces with ordinary semicolon-terminated arms. Filed while writing the block-value regression example (0040); the example sidesteps it with positive arm values. ## Reproduction ```sx classify :: (n: i32) -> i32 { if n == { case 0: 100; case 1: 10; else: -1; // ← negated literal arm → phi width mismatch } } main :: () -> i32 { classify(1) } ``` Expected: compiles, `classify(1)` returns 10. Actual: LLVM verification failure. Workaround: give the arm an explicitly-typed value (`else: { x : i32 = -1; x }`) or avoid the negation. ## Investigation prompt Look at the match-as-value lowering in `src/ir/lower.zig` (`lowerMatch`, the `has_value_merge` path ~line 4500, and the arm `result_type` inference ~line 11698). The arm value is lowered via `lowerBlockValue(arm.body)` then `coerceToType(v, v_ty, result_type)`. For a negated-literal arm the value's type comes out narrower than `result_type` (i64 here), and the coercion path that should widen it before the `br merge_bb, {v}` either runs against the wrong target or is skipped — so the phi gets an i32 operand under an i64 result. Make the arm value coerce to the merge's `result_type` consistently (mirror how the positive-literal arms are handled), or set `target_type = result_type` while lowering each arm body so the negate picks the right width. Verify with the repro above (expect exit 10) and add a regression example. ## Status OPEN. Pre-existing match-value codegen quirk, surfaced (not caused) by the block-value work.