attempt-2 review fixes (docs-only; contract mechanics confirmed sound): - README + S0.2 grep-clean: 'S0 HEAD == base' / 'S0 == base' were inaccurate (HEAD carries the docs/examples/tests diff). Reword to: production/compiler behavior is base-equivalent — zero src/ changes, single-author output byte-identical to base by construction — HEAD is a distinct commit, not base. - S0.3 ledger: drop the stale '116-class corpus' FFI wording for the grounded live count (96 entry trees / 95 active markers), matching the S0.1 count note. No partition / manifest / examples / harness change. Gate green: zig build + zig build test (LSP sweep 574, no crash) + run_examples (540/0); m3te ios-sim build via main binary exit 0.
8.0 KiB
S0.2 — E6b disposition, the two-corpus partition, and the E6BR-5 re-file
Authority: runs/stdlib/design/fork-c-plan/planspec-r3.json (S0.2) +
runs/stdlib/design/fork-c-deepdive/reconciled.md (§3 one-resolver-two-timings, §6
roadmap, §8 fold-in). Base: wt-stdlib-base @ 1f75528 (A–E6a merged). E6b:
flow/stdlib/E6b @ af737b0 (PAUSED, unmerged). This is documentation only — no
production code change.
1. E6b transitional src is NOT merged
The transitional E6b source on flow/stdlib/E6b @ af737b0 is not brought onto the
Fork C baseline. All of it is destined for S3/S6 deletion under Fork C:
- the route-all engine + the type-reference choke-point
(
resolveRegistrationSigTypeInSource/sig_registration_mode) —lower.zig,protocols.zig; - the executable grep gate
src/ir/e6br_gate.test.zig(+ itsir.zigimport); - the supporting
calls/lower/protocols/type_bridge/type_resolver/typeschanges.
Grounded reasons it is transitional, not load-bearing: the whole-AST resolver walks
every reference position, so it closes the protocol/param-impl signature surface
the choke-point policed (reconciled §3/§4 T4); and the grep gate is unnecessary once
the leaf it polices no longer exists (reconciled §5). A–E6a stays merged purely as
proof-of-semantics + per-decl nominal infra (internNominal / nominal_id==0
byte-identity rule / RawDeclRef facts → the DeclId seed) — see
S0.3-reuse-delete-ledger.md.
Grep-clean (verified on this branch — src/ is base-equivalent, zero src changes):
| check | base / S0 | E6b |
|---|---|---|
resolveRegistrationSigTypeInSource in src/ |
absent | present (lower.zig) |
sig_registration_mode in src/ |
absent | present (lower.zig, protocols.zig) |
src/ir/e6br_gate.test.zig |
absent | present |
walkConcreteSigArgs in src/ir/lower.zig |
absent | present (the E6BR-5 site) |
Because S0 introduces no production code change, these remain absent on the Fork C baseline by construction.
2. Harvested resolver-acceptance corpus + the two-corpus partition
Harvested by copying the example trees + their expected goldens ONLY (never the transitional src):
examples/0811–0829(19 trees) fromflow/stdlib/E6b @ af737b0— error-set / protocol / param-impl / route-all same-name ambiguity & own-wins surfaces;examples/0795–0798(already merged on the base) — the enum/union ambiguous/own-wins pair.
The corpus is partitioned by empirically running each harvested case through the
current base compiler and comparing its output to the E6b TARGET golden (the exact
method: build, then sx run examples/<name>.sx, normalize with the
run_examples.sh rules, diff against the E6b golden):
(a) BASELINE-GREEN — the mirror-equivalence corpus
Harvested cases whose old selector is already CORRECT on wt-stdlib-base today
(actual == E6b target, byte-for-byte). They get standard
examples/expected/<name>.{exit,stdout,stderr} markers, are run by
tests/run_examples.sh, and are locked into the S0 baseline. This set is the S2
assert-only Debug mirror's ONLY oracle.
| case | exit | proof it is already-correct on base |
|---|---|---|
0795-modules-same-name-enum-ambiguous |
1 | already merged + green (E6a) |
0796-modules-same-name-enum-own-wins |
0 | already merged + green |
0797-modules-same-name-union-ambiguous |
1 | already merged + green |
0798-modules-same-name-union-own-wins |
0 | already merged + green |
0823-route-all-own-wins-subform-wrappers |
0 | base output == E6b target (opt=1 arr=2 sl=3 dep=99) |
0828-protocols-param-impl-arg-wrapped-own-wins |
0 | base output == E6b target (tag=7 dep=9) |
(b) RESOLVER-TARGET — known-wrong old behavior
Harvested cases (and the re-filed E6BR-5) where the old selector is wrong on the
E6b-unmerged base (silently resolves last-wins / under-diagnoses / picks the wrong
author / fails own-author resolution). They are held in a documented, listed,
separate harness at tests/resolver-target/ with NO active examples/expected/
marker (so run_examples.sh does not run them), but WITH their TARGET output
recorded and an enumerated manifest (tests/resolver-target/manifest.md, 18
cases). The sibling xfail runner run_resolver_target.sh runs each and asserts it
currently FAILS — so the set is never silently dropped. It flips to active + green
at S3.9.
The 17 harvested 08xx resolver-target cases: 0811, 0812, 0813, 0814, 0815, 0816, 0817, 0818, 0819, 0820, 0821, 0822, 0824, 0825, 0826, 0827, 0829. Per-case class,
base-now behavior, and target are in the manifest.
0811 and 0829 placement (required one-liners):
- 0811 → resolver-target. Old selector is wrong here on the E6b-unmerged base:
the five bare error-set forms (
size_of/ annotation / type-as-value / match-arm /!IoErrchannel) each silently resolved one global last-winsIoErrvia thetype_bridge.resolveInlineErrorSetfindByNameshort-circuit and the program exited 0; the target is five loud "type 'IoErr' is ambiguous" diagnostics + exit 1. - 0829 → resolver-target. Old selector is wrong here on the E6b-unmerged base:
the concrete
*Boxprefix of the mixed pack-closure source fell to the no-authortype_bridge.resolveTemplateSignatureTypewrapper (global last-wins) and registered silently (exit 0); the target is a loudBoxambiguity + exit 1.
3. E6BR-5 re-filed into resolver-target
E6BR-5 (the open nested-pattern ambiguity hole that paused E6b) is re-filed into the resolver-target set as a regression — explicitly NOT an E6b attempt-6.
- What it is:
walkConcreteSigArgs(E6blower.zig:14686) skips any direct arg that has an unbound part instead of recursing into it, so a nested concrete leaf (*BoxinsideClosure(Closure(*Box, ..$inner) -> $IR, ..$args) -> $R) is never ambiguity-checked; the impl compiled rc=0. Onwt-stdlib-base(E6BR-4 unmerged) both the direct and nested concrete leaf silently resolve via the pre-E6BR-4 no-author wrapper path, so the reproducer exits 0 with no diagnostic. - Subsumption (one line): the whole-AST resolver walks every reference position —
including nested parameterized-pattern leaves — so the nested
Boxis ambiguity-checked by construction and the "skip a nested arg" hole cannot exist. - Form: an authored reproducer lives at
tests/resolver-target/cases/e6br5-nested-pack-source-ambiguous.sx(self-contained; verified to exit 0 silently on the base — the fail-before). Its target is a spec (exit 1 +Boxambiguous), with exact bytes produced by the resolver at S3.9 (expected/e6br5-…target.md).
4. The mirror / flip statement (locked)
- S2's mirror asserts
resolver == old-selectorover the BASELINE-GREEN corpus ONLY. It never asserts new == old over the resolver-target corpus (the old selector is a wrong oracle there), and it never selects for lowering (assert-only, Debug-only, deleted in the S3.10 commit that completes the cutover). - S3.9 flips the resolver-target corpus to active + green, validated against each
case's TARGET output (not against the old selectors). After the flip, the goldens
move from
tests/resolver-target/expected/toexamples/expected/, the harness goes empty, and these cases stay green through S6.
5. Acceptance (S0.2) — self-check
- ✅ Written disposition: E6b transitional src not merged (§1, grep-clean table).
- ✅ Harvested corpus recorded + partitioned: baseline-green (markers, locked, mirror-equivalence) vs resolver-target (enumerated manifest, separate listed harness, no active marker, TARGET goldens present, currently xfail, never dropped) — §2.
- ✅ 0811 and 0829 each in resolver-target with the "old selector is wrong on the E6b-unmerged base" one-liner — §2.
- ✅ E6BR-5 re-filed into resolver-target with the subsumption one-liner, NOT an E6b attempt-6 — §3.
- ✅ Mirror/flip statement recorded — §4.
- ✅ No transitional E6b src on the Fork C baseline (grep-clean) — §1.