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.
144 lines
8.0 KiB
Markdown
144 lines
8.0 KiB
Markdown
# 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` (+ its `ir.zig` import);
|
||
- the supporting `calls` / `lower` / `protocols` / `type_bridge` / `type_resolver` /
|
||
`types` changes.
|
||
|
||
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) from `flow/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 /
|
||
`!IoErr` channel) each silently resolved one global last-wins `IoErr` via the
|
||
`type_bridge.resolveInlineErrorSet` `findByName` short-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 `*Box` prefix of the mixed pack-closure source fell to the no-author
|
||
`type_bridge.resolveTemplateSignatureType` wrapper (global last-wins) and registered
|
||
silently (exit 0); the target is a loud `Box` ambiguity + 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` (E6b `lower.zig:14686`) **skips** any direct arg
|
||
that has an unbound part instead of **recursing** into it, so a nested concrete leaf
|
||
(`*Box` inside `Closure(Closure(*Box, ..$inner) -> $IR, ..$args) -> $R`) is never
|
||
ambiguity-checked; the impl compiled rc=0. On `wt-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 `Box` is
|
||
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 + `Box` ambiguous), 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-selector` over 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/` to `examples/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.
|