Skip to content

a generic body binds an unannotated optional local to register zero, and never releases its shell #1010

Description

@kacy

Found while fixing #993, and deliberately left out of that change. Three residuals in the same region.

the compare answers wrong

fn f[T](t: T) -> Int:
    s: String? := none
    if s == none:
        return 1
    return 0

takes the else branch. The comparison falls through to a raw pointer equality against zero, and the shell's address is never zero — the same mechanism #987 fixed for a bare-none binding at the top level. It is a silent wrong answer.

It was not fixed with #993 because it routes through ir_generic_param_optional_tid rather than ir_emission_tid, and wiring the locals map into that path also drags in the ownership releases on it, which is a larger change than the bind fix.

only the annotated local is fixed

if let v = f() and s := f() inside a generic body still bind register zero. Recovering the shape there needs the callee's declared return type, which is a different recovery path — and really wants generic bodies to be type-checked at all, which is #927 stage 5.

the shell is never released

A generic body's optional shell has no owner: a specialization keeps no tuple local, so nothing releases it. Measured unchanged across #993 at 15.1 mb against 52.7 mb over the usual round counts.

Separately, a lambda body runs no reference-counting prologue at all, so it tracks and releases no locals: a plain s := "x" in a lambda grows 10.5 mb to 38.7 mb with no if let involved anywhere.

Both are pinned by failing twins in tests/pending/if_let_frame_ownership.pith rather than in tests/leaks/, since a known-failing reproducer in the gate directory would just make the gate red.

All of these point the same way: generic and lambda bodies are emitted with information the checker never produced for them, and each symptom gets patched where it surfaces. #927 stage 5 is the change that removes the category.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions