Skip to content

net: span the embedded-pointer class across all five decode routes - #50

Merged
twmb merged 1 commit into
mainfrom
net-embed-routes
Aug 5, 2026
Merged

net: span the embedded-pointer class across all five decode routes#50
twmb merged 1 commit into
mainfrom
net-embed-routes

Conversation

@twmb

@twmb twmb commented Aug 5, 2026

Copy link
Copy Markdown
Owner

A real hole in the suite, found by auditing the TestRegression battery.
Stacked on #49. No behavior change — this is test coverage only.

The gap

fieldByIndex refuses to write through a nil unexported embedded pointer,
because Go reflection cannot allocate one. That refusal has five call sites.
The suite proved it on one:

call site route before
unsafe.go deserRecordFast binary (compiled) only via one regression pin
json_decode.go decodeRecordStruct x2 JSON present-key, JSON default-fill covered by nothing
resolve.go deserStruct x2 resolved writer-op, resolved reader-default covered by nothing

Four of five routes had no test at all. Neutering each left the pin green.

Behavior is correct on all five

Verified against encoding/json, which refuses the identical shape for the
same reason — json: cannot set embedded pointer to unexported struct — and
which fieldByIndex's own comment already claimed parity with. That claim was
executed rather than trusted. No bug here; a class proven on one route in
five.

Why the generative net missed it

TestGenerative_EmbedShapeWalkerAgreement generates a pointer embed on half of
its 16,000 shapes — and then called allocPointers on every one before
encoding. So for the net's entire history the occupancy axis carried a single
value
while the shape axis looked fully crossed. A net can be enormous and
still be blind along an axis it appears to sweep.

What now spans it

  • TestMatrix_NilEmbedPointerRouteAgreement — occupancy {nil, pre-allocated}
    x exportedness x route {5 decode sites}, plus the 3 encode sites against an
    all-zero map twin. encoding/json gives the accept/reject verdict cell by
    cell, with a guard that fails if the oracle ever answers uniformly.
  • TestInvariant_EveryFieldByIndexSiteHasARouteCell — derives the call-site
    set by AST scan and reds in both directions, so a new caller cannot ship
    unexercised. It caught a mis-keyed table entry on its first run.
  • roundTripNilEmbed — the occupancy arm inside the generative net. 7,544
    round trips now carry a nil pointer embed, with a liveness floor that fails
    if the axis goes dead again.

Neuter gate — one distinct red per mechanism

neutered arm new matrix generative old pin
unsafe.go compiled decode RED green RED
json_decode present-key RED green green
json_decode default-fill RED green green
resolve.go writer-op RED green green
resolve.go reader-default RED green green
fieldByIndexZero nil detection RED RED panics
fieldTypeByIndex leaf resolution green RED green

Every red: exit != 0, RUN > 0, no panic:, each naming its own cell. The four
green cells in the pin column are the gap. The last row is a deeper-index-path
defect only the generative arm can see — the hand matrix's 1-deep path makes
that neuter a no-op, which is why both extensions earn their place.

Coverage: 4 blocks covered-by-nothing and 4 reachable-only-via-regression are
now netted. Only-regression 183 -> 179, dark 284 -> 279. Suite green, -race
green.

The embed net generated a pointer embed on half its 16,000 shapes and then
called allocPointers on every one before encoding, so the OCCUPANCY axis
carried a single value: every generated pointer embed reached the codecs
ALLOCATED. The nil arm was reached by nothing but an instance pin.

Worse on the decode side. fieldByIndex's refusal to write through a nil
UNEXPORTED embedded pointer has five call sites -- the compiled binary
decoder, JSON decode's present-key and default-fill arms, and the resolved
decoder's writer-op and reader-default arms. TestRegression_EmbeddedPointer-
StructNoPanic pinned one. The other four error arms were executed by no test
in the suite at all.

Behavior is correct on all five (verified against encoding/json, which
refuses the same shape for the same reason and which fieldByIndex's comment
already claimed parity with) -- this closes the net, it does not fix a bug.

  - TestMatrix_NilEmbedPointerRouteAgreement: occupancy {nil, pre-allocated}
    x exportedness {exported, unexported} x route {5 decode sites}, plus the
    3 encode sites against an all-zero map twin. encoding/json supplies the
    accept/reject verdict cell by cell.
  - TestInvariant_EveryFieldByIndexSiteHasARouteCell: derives the call-site
    set from source by AST scan and reds in BOTH directions -- a new site
    landing without a cell, or a listed site going away.
  - roundTripNilEmbed: the occupancy arm inside the generative net, now
    7,544 of its round trips carry a NIL pointer embed, with a floor that
    fails if the axis goes dead again.

Neuter evidence, one distinct red per mechanism (exit != 0, RUN > 0, no
"panic:"):

  neutered arm                     matrix   generative   old pin
  unsafe.go deserRecordFast         RED        green      RED
  json_decode present-key           RED        green     green
  json_decode default-fill          RED        green     green
  resolve.go writer-op              RED        green     green
  resolve.go reader-default         RED        green     green
  fieldByIndexZero nil detection     RED        RED      panics
  fieldTypeByIndex leaf resolution  green       RED      green

The four green cells in the old-pin column are the gap this closes; the last
row is a defect only the generative arm's deeper index paths can see.

Coverage: 4 blocks went from covered-by-nothing to covered, 4 from
reachable-only-via-TestRegression to covered. Full suite green, -race green.
Base automatically changed from test-consolidation to main August 5, 2026 23:03
@twmb twmb closed this Aug 5, 2026
@twmb twmb reopened this Aug 5, 2026
@twmb
twmb merged commit d1d0725 into main Aug 5, 2026
3 checks passed
@twmb
twmb deleted the net-embed-routes branch August 5, 2026 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant