Follow-up split out of #198 (P-007 Pool/Span). Deliberate deferral — recorded with evidence, per #198's "a deliberate deferral beats a soft false positive."
The uncovered shape
A pooled buffer's view is cached into a field, and that view field is read after the buffer is Returned in a different member:
sealedclassViewEscapeField:IDisposable{privatebyte[]_buf;privateMemory<byte>_view;publicvoidSetup(intn){_buf=ArrayPool<byte>.Shared.Rent(n);_view=_buf.AsMemory(0,n);}// bounded view -> fieldpublicvoidDone()=>ArrayPool<byte>.Shared.Return(_buf);// releasepublicbyte[]Late()=>_view.ToArray();// reads the field view AFTER the returnpublicvoidDispose(){}}Verified against the current extractor + core (dotnet run … --flow-locals → python -m ownlang ownir): nothing fires. The view is bounded (so no POOL005/OWN025 over-read), and the use-after-return (POOL004/OWN002) is never surfaced because the Return and the field-view read live in different members.
Why it is deferred, not fixed
Whether this is a bug depends on the caller's method-call order, which a per-method + field pass cannot see:
Setup → Done → Late — use-after-return (the bug).Setup → Late → Done — perfectly fine.
Flagging it unconditionally would be a soft false positive (P-007 §Non-goals: whole-program/interprocedural Span/Memory escape is out of v0 scope). It needs interprocedural / whole-program ordering (or a conservative "view field outlives a class-wide Return with no ordering proof" heuristic that would have to clear the corpus zero-FP gate).
What #198did deliver
The materialization side is covered and now pinned: a full-length view stored into a field (_view = _buf.AsMemory()) is caught at the store as an OWN025 over-read (corpus arraypool-view-into-field-overread). This issue is only the bounded-view object-level escape left past that boundary.
Done when
The cross-member field-view-after-Return escape is caught (POOL004 → OWN002) with a corpus bad/ok pair, without any new false positive on the existing corpus (the Setup → Late → Done order and every current ok-fixture stay silent).
Refs: docs/proposals/P-007-arraypool-span.md; corpus/real-world/arraypool-view-into-field-overread/notes.md.
Follow-up split out of #198 (P-007 Pool/Span). Deliberate deferral — recorded with evidence, per #198's "a deliberate deferral beats a soft false positive."
The uncovered shape
A pooled buffer's view is cached into a field, and that view field is read after the buffer is
Returned in a different member:Verified against the current extractor + core (
dotnet run … --flow-locals→python -m ownlang ownir): nothing fires. The view is bounded (so no POOL005/OWN025 over-read), and the use-after-return (POOL004/OWN002) is never surfaced because theReturnand the field-view read live in different members.Why it is deferred, not fixed
Whether this is a bug depends on the caller's method-call order, which a per-method + field pass cannot see:
Setup → Done → Late— use-after-return (the bug).Setup → Late → Done— perfectly fine.Flagging it unconditionally would be a soft false positive (P-007 §Non-goals: whole-program/interprocedural
Span/Memoryescape is out of v0 scope). It needs interprocedural / whole-program ordering (or a conservative "view field outlives a class-wideReturnwith no ordering proof" heuristic that would have to clear the corpus zero-FP gate).What #198did deliver
The materialization side is covered and now pinned: a full-length view stored into a field (
_view = _buf.AsMemory()) is caught at the store as an OWN025 over-read (corpusarraypool-view-into-field-overread). This issue is only the bounded-view object-level escape left past that boundary.Done when
The cross-member field-view-after-
Returnescape is caught (POOL004 → OWN002) with a corpus bad/ok pair, without any new false positive on the existing corpus (theSetup → Late → Doneorder and every current ok-fixture stay silent).Refs: docs/proposals/P-007-arraypool-span.md; corpus/real-world/arraypool-view-into-field-overread/notes.md.