# 0062 — generic function with a value-carrying `!` return miscompiles > **✅ RESOLVED (2026-06-01) — NOT A BUG (invalid repro syntax).** The repro used > the non-generic form `(T: type, …)` / `(T: Type, …)` — a plain value param of > type `Type`, NOT a generic type parameter. Per `specs.md` (the `$` sigil > introduces a generic type parameter), a function generic type param must be > `$T: Type`. With the correct form, generic value-carrying failable composition > (ERR E5.1 sub-feature 8) works fully: > > ```sx > wrap :: ($T: Type, f: Closure() -> (T, !E)) -> (T, !E) { return try f(); } > wrap(s32, closure(() -> (s32, !E) { return 7; })) catch e -1 // 7 > r, err := wrap(s32, closure(() -> (s32, !E) { return 9; })) // r=9 > wrap(s32, closure(() -> (s32, !E) { raise error.Bad; })) catch e -1 // -1 > ``` > > The only real (separate, orthogonal) defect found: a NON-`$` `T: Type` function > param used as a type silently resolves to an empty `{}` (renders `T{}`) instead > of erroring — tracked as **issue 0064**, deferred (not ERR-scoped). ## Symptom A generic function whose return type is a value-carrying failable in the generic type param — `wrap :: (T: type, …) -> (T, !E)` — does not substitute `T` in the failable return tuple during monomorphization. Observed two ways: - Consumed via `catch`: `LLVM verification failed: PHI node operands are not the same type as the result!` — the success branch carries `{}` (an unsubstituted / empty value) while the handler branch carries the real success type. - Consumed via destructure: the success value renders as `T{}` (the literal generic type name) instead of the concrete value, and the error slot is wrong. Expected: `T` is bound to the concrete monomorphization type (`s32`), the success value flows through as `7`, and the error slot is `0` on success. ## Reproduction ```sx #import "modules/std.sx"; E :: error { Bad } wrap :: (T: type, f: Closure() -> (T, !E)) -> (T, !E) { return try f(); } main :: () -> s32 { // catch form → LLVM phi type mismatch: r := wrap(s32, closure(() -> (s32, !E) { return 7; })) catch e -1; print("{}\n", r); // want 7 return 0; } ``` Destructure form (same root cause, different surfacing): ```sx r, err := wrap(s32, closure(() -> (s32, !E) { return 7; })); print("{} {}\n", r, xx err); // prints "T{} s64"; want "7 0" ``` ## Investigation prompt The bug is in monomorphizing a value-carrying failable return type in [src/ir/lower.zig](../src/ir/lower.zig). `monomorphizeFunction` (~10259) / `resolveReturnType2` (~8309) resolve the return type under `type_bindings` (`$T` → concrete). For a plain `-> T` this works; for `-> (T, !E)` the value slot `T` of the failable tuple appears NOT to be substituted — the success value stays the unsubstituted generic type (rendering as `T{}` / an empty `{}` in IR), so `lowerFailableSuccessReturn` / `extractSuccessValue` and the `try` success path produce a value of the wrong type, which the `catch` merge phi then rejects. Likely fix: ensure the failable-tuple return type is re-resolved through `type_bindings` during monomorphization (the tuple's value fields, not just a top-level `$T`), and that `failableSuccessType` / the `try`/`catch` success extraction use the substituted tuple. Verify with both repros above (catch → prints 7; destructure → prints "7 0"). This is ERR E5.1 sub-feature 8 (generic functions with `!` returns); the program-wide shape-union slice deliberately excluded generic shapes pending this fix.