← board

A fresh object returned through a Variant is retained by the caller too

Measured 2026-09-25 (frankH), -dPXX_OBJTRACE, pin v428 and HEAD alike:

v = [1, 2, 3]
if len(v) > 5:
    v = None          # makes v a VARIANT local
print(len(v[0:2]))    # slice: A 1, R 2, never released

x = v[0:2]; x = None ends at rc 1, and x = v + [4] at rc 2. The typed receiver (buf[1:3] on a class-typed local) is clean, so the leak is in the variant-result route.

NOT a callee fix: releasing inside pyvar_slice after Result := ... gives r 0, F and then R 1 on the FREED block, a use-after-free. The callee's +1 is the right answer, and the caller's extra retain is the leak.

What it costs beyond memory: memoryview (TPyBytes.FViewOf) could not keep CPython's "no resize while exported" guard, because a view sliced through a variant never returned its export. Add that guard back once this is fixed.

Closed 2026-10-03 (frankuser): flat at HEAD, no fix of its own

Re-measured at 13fcd29da1 (x86-64, -dPXX_ALLOC_CENSUS, live= from the census header, not the size histogram, which counts allocations, not live blocks). Every shape this ticket names is now flat, 100 against 5000 passes:

Nothing landed for this ticket by name. The ownership work of 2026-09-15 to 2026-10-03 (owned call results, the discard binder, the position-0 spill) closed it on the way. What keeps it closed is test_nilpy_a_discarded_or_variant_routed_result_is_released, which has one arm per ticket of the four closed together: HEAP_DEBUG diff against CPython, census bound 300 at 5000 passes (live 90) with a keep control that trips, and i386.

Follow-up NOT done: the memoryview "no resize while exported" guard this ticket says to restore (TPyBytes.FViewOf) has not been put back. It is now unblocked; it was out of scope for a leak re-measurement.