← board

Measured 2026-09-10, compiler b7745aaf0a59

lekkerzeilen/ui.py:414:

if keep is not None:
    self.mark(*keep)

error: *unpacking into Places.mark is not supported

Why this is filed as a sibling and not as a new discovery

bug-n-double-star-unpacking-is-rejected-at-a-method-call records ** being refused at a method call. This is * at the same position. CLAUDE.md's rule is explicit about this shape: "Fixed one arm of a double case? Grep for the sibling before closing." Filing it separately is how the grep gets done in advance rather than hoped for.

The right fix is probably one change covering both stars at a method call, and a fix that lands only one should say in its resolution why.

RESOLVED 2026-09-10 — the fix is frankZ's f98fd53d7

*unpacking into a method or a constructor with defaults compiles and runs. PyStarExpandCallArgs — the ONE central expander, five call sites, so every door is covered by one change — initialises each optional slot from DefaultArgValueNode and overwrites it from the sequence under a pystar_has1 guard, and the arity guard's lower bound became required instead of wanted. No new pylib builtin, so nothing here is inert until the next pin.

self.mark(*keep) at lekkerzeilen/ui.py:414 works. sim.py is clean; rig, traffic, vessel and ui each advanced to a different wall.

Two seats reached this defect independently and inside one hour, and frankZ landed first. This resolution is the losing seat's; what follows is only the part that is not already in that commit. Its own write-up is the record of the fix.

The sibling ticket predicted a design boundary. Both seats measured that it was not.

bug-n-double-star-unpacking-is-rejected-at-a-method-call says, correctly for what it could see: "* at a method call is implemented, with a deliberate and honestly stated limit: it is a compile-time expansion, so it cannot reconstruct defaults. That is a design boundary, and widening it means runtime argument binding." No runtime argument binding was needed. The compiler already constructs a default's VALUE at a call site, every time anyone writes a short ordinary call, and it already had a run-time length probe next door. The refusal message was true about pystar_arg and false about the compiler, and it stood for a month because nobody re-measured the thing the message asserted.

What the fix does NOT own, measured rather than assumed

The pre-fix compiler refuses the added test file at its first constructor row, so the whole file going red-to-green says nothing about the rows below that point. Cut down to only the plain-function rows, the pre-fix compiler runs them green. They were never broken:

door mechanism defaults before the fix
plain function f(*xs) PyStarMixedForwardCallPyStarForwardCall, a RUN-TIME dispatch on len(args) already correct
method / constructor PyStarExpandCallArgs, a COMPILE-TIME expansion refused outright

Two mechanisms for one concept, and only the second was broken (devdocs/dev/normalise-dont-special-case.md). Neither commit's test may quote a plain-function row as evidence for the fix, and test_nilpy_star_unpack_into_a_target_with_defaults.npy says so in its header.

The ** sibling is NOT fixed, and this is why

The double-case rule says a fix landing one arm must say why. It is not one change, and the table above is the reason:

So the ** doors need a receiver-aware forwarder — a firstSlot through PyStarMixedForwardCall/PyStarForwardCall plus a receiver hoisted into slot 0 — a different and larger change than teaching an existing expansion about defaults. The sibling's own recommendation ("the ** half is the one to fix first") was written before either mechanism was traced; on the measurement it is the harder half, not the easier one. The trace is appended to that ticket so whoever takes it does not repeat it.

The census artefact frankuser asked to have recorded here

Five modules answered the *unpacking error and there were three sites. rig, traffic and vessel all reported pascal26:239 while their own line 239 is blank or unrelated: they are blocked by sim.py's site through the import, and they wear sim's line number. An error-string census over-counts by the import fan-in — anyone counting strings gets 5, anyone opening the files gets 3. The same artefact is live right now on the pascal26:156: error: Variant :=: this scalar type not yet supported rows in the same three modules. frankuser hit this while reading a census of mine and asked for it to be recorded on this ticket; it is the strongest argument yet for a per-subject report that prints the FILENAME beside every failure, which would have shown 3 without anyone opening anything.

Added on top of f98fd53d7

test/test_nilpy_star_unpack_into_a_target_with_defaults.npy and its Makefile rows, covering the doors that commit's own test has no row for:

Log