spec: 23 — correct prep-commit reachability against main

Brainstorm assumed all four 23.4-prep commits had shipped to main.
Branch verification (post-iter/23.4 deletion) showed only prep1
(linearity + check bare-name) is on main; prep2 + prep3 were
attempted on the stranded iter/23.4 branch and never landed.

Spec corrections:
- Goal section: prep-commit status block reflects actual main state.
- Architecture: drop §2 (prep2/prep3 rollback) — no rollback exists
  on main; section count drops from four to three artefacts.
- Components table: prep2/prep3 row now reads 'abandoned 2026-05-11
  with iter/23.4 deletion', not 'shipped, rolled back in 23.4'.
- Acceptance criterion 1: drop the 'prep2 + prep3 are rolled back'
  clause.
- Load-bearing assumption 5: now states prep2/prep3 never reached
  main (fixes the silent-assumption pattern this spec exists to
  prevent — same failure mode the original Spec-23 had).
- Load-bearing assumption 6: cite the cherry-picked main SHAs
  (0caaced, 923dd8c) alongside the stranded-branch originals
  (8d39f13, aef4ab8).
- Known costs: drop the '23.4 rollback' line item.
This commit is contained in:
2026-05-11 22:04:49 +02:00
parent f7ca26c5b4
commit 841d65d88c
+35 -48
View File
@@ -32,10 +32,20 @@ seam.
The corrected architecture unifies the two specialisers (see The corrected architecture unifies the two specialisers (see
Architecture below) and ships the remaining free fns on top of Architecture below) and ships the remaining free fns on top of
the unified pass. The three iter-23.4 prep commits are classified: the unified pass.
prep1 (linearity + checker bare-name) stays load-bearing, prep2 +
prep3 (codegen bare-name fall-throughs) become provably dead and **Prep-commit status (verified against main 2026-05-11 after
are rolled back in 23.4. iter/23.4 branch teardown):** prep1 (linearity + checker
bare-name) landed on main on 2026-05-11 via cherry-pick from the
stranded iter/23.4 branch; it stays load-bearing. prep2 and prep3
(codegen bare-name fall-throughs) were attempted on the stranded
iter/23.4 branch and *never reached main*; with iter/23.4 deleted,
they are abandoned as git history without a rollback step. Their
architectural intent — make codegen handle bare polymorphic
free-fn names directly — is superseded by the mono-unification.
The unified pass rewrites bare polymorphic call sites to mono
symbols before codegen runs, making the fall-throughs structurally
unnecessary.
`Show`, operator routing, `print`-rewire, and the heap-Str ABI `Show`, operator routing, `print`-rewire, and the heap-Str ABI
remain out of scope; each is its own milestone with substantive remain out of scope; each is its own milestone with substantive
@@ -44,7 +54,7 @@ reasons (see "Out of scope" — unchanged from original spec).
## Architecture ## Architecture
The milestone no longer consumes the 22b.3 typeclass machinery The milestone no longer consumes the 22b.3 typeclass machinery
unchanged. Four artefacts: unchanged. Three artefacts:
### 1. Mono-Pass unification (the corrected centrepiece) ### 1. Mono-Pass unification (the corrected centrepiece)
@@ -80,33 +90,7 @@ sites of `lower_polymorphic_call` (lines 1944, 1972) become direct
calls to mono symbols after the typecheck-mono walker has rewritten calls to mono symbols after the typecheck-mono walker has rewritten
them. them.
### 2. Rollback of iter-23.4-prep2 + prep3 ### 2. Prelude AILang module
Two existing codegen bare-name fall-throughs were anticipatory
patches for the prelude free fns:
- commit `a06159d` (prep2): codegen — bare-name fall-through to
implicit-imported free fns.
- commit `c42a0f5` (prep3): codegen — polymorphic-free-fn bare-name
fall-through to implicit-imported modules.
After Mono unification, codegen never sees bare polymorphic free-fn
names — the unified mono pass rewrites every call site to its mono
symbol before codegen runs. The two patches are provably dead and
are rolled back in 23.4. The rollback lands in the same iter as
the unification so the codebase never carries the fall-throughs
as visible-but-dead code.
The third iter-23.4-prep is kept:
- commit `8d39f13` (prep.1): linearity — register `Def::Class` method
types in globals. Required independent of mono — linearity walks
pre-mono.
- commit `aef4ab8` (prep.2): check — bare-name fall-through to
implicit-imported free fns. Required at typecheck time — bare `ne`
must resolve to the prelude `Def::Fn` *before* mono can specialise.
### 3. Prelude AILang module
`examples/prelude.ail.json` already contains, from iters 23.123.3: `examples/prelude.ail.json` already contains, from iters 23.123.3:
the `Ordering` ADT, the `Eq` class with `Eq Int`/`Bool`/`Str` the `Ordering` ADT, the `Eq` class with `Eq Int`/`Bool`/`Str`
@@ -119,7 +103,7 @@ Iter 23.5 adds the five free fns:
bodies pattern-matching `compare` against the appropriate bodies pattern-matching `compare` against the appropriate
`Ordering` shapes. `Ordering` shapes.
### 4. C-runtime functions ### 3. C-runtime functions
`runtime/str.c` shipped its two functions in iter 23.2 and 23.3: `runtime/str.c` shipped its two functions in iter 23.2 and 23.3:
`ail_str_eq(a, b) -> bool` (byte-equality on constant-string layouts) `ail_str_eq(a, b) -> bool` (byte-equality on constant-string layouts)
@@ -139,9 +123,9 @@ Int/Bool/Str is acknowledged and ratified as transitional.
| 23.1 | shipped (2026-05-10) | `Ordering` ADT + prelude skeleton + auto-load via `check_workspace`. | | 23.1 | shipped (2026-05-10) | `Ordering` ADT + prelude skeleton + auto-load via `check_workspace`. |
| 23.2 | shipped (2026-05-10) | `class Eq` + `Eq Int/Bool/Str` + `ail_str_eq`. | | 23.2 | shipped (2026-05-10) | `class Eq` + `Eq Int/Bool/Str` + `ail_str_eq`. |
| 23.3 | shipped (2026-05-10) | `class Ord extends Eq` + `Ord Int/Bool/Str` + `ail_str_compare`. | | 23.3 | shipped (2026-05-10) | `class Ord extends Eq` + `Ord Int/Bool/Str` + `ail_str_compare`. |
| 23.4-prep | shipped, **kept** | commits `8d39f13` (linearity registers `Def::Class` method types in globals) + `aef4ab8` (check bare-name fall-through to implicit-imported free fns). Both resolve names *before* mono; independent of B1. | | 23.4-prep | shipped to main 2026-05-11 (cherry-picked from stranded iter/23.4), **kept** | commits on main: `0caaced` (linearity registers `Def::Class` method types in globals) + `923dd8c` (check bare-name fall-through to implicit-imported free fns). Both resolve names *before* mono; independent of B1. |
| 23.4-prep2 / 23.4-prep3 | shipped, **rolled back in 23.4** | commits `a06159d` + `c42a0f5` codegen bare-name fall-throughs. Provably dead after Mono unification. | | 23.4-prep2 / 23.4-prep3 | **abandoned 2026-05-11 with iter/23.4 deletion** — never reached main | Attempted-but-stranded commits were `a06159d` + `c42a0f5` (codegen bare-name fall-throughs); they were anticipatory patches for an approach (codegen-time bare-name handling) the mono-unification supersedes. No rollback step is needed because no rollback target exists on main. |
| **23.4** (revised) | upcoming | **Mono-Pass unification.** Restructure `crates/ailang-check/src/mono.rs::monomorphise_workspace` into one specialiser with two source-body entry points (class-method via `Registry::entries`, free-fn direct). Extend `collect_mono_targets` to also produce targets for polymorphic free-fn calls with fully-concrete substitutions. Remove `lower_polymorphic_call` + `module_polymorphic_fns` + `mono_queue` from codegen. Rollback prep2 + prep3. Amend DESIGN.md §"Resolution and monomorphisation" to describe the pass as covering all `Type::Forall`-Defs. Tests: existing polymorphic fixtures (`poly_id`, `poly_apply`, `poly_rec_capture`) green; new fixture `cmp_max_smoke` proves cross-cutting (`cmp_max : forall a. Ord a => (a, a) -> a` at Int synthesises both `cmp_max__Int` and nested `compare__Int` in one fixpoint). | | **23.4** (revised) | upcoming | **Mono-Pass unification.** Restructure `crates/ailang-check/src/mono.rs::monomorphise_workspace` into one specialiser with two source-body entry points (class-method via `Registry::entries`, free-fn direct). Extend `collect_mono_targets` to also produce targets for polymorphic free-fn calls with fully-concrete substitutions. Remove `lower_polymorphic_call` + `module_polymorphic_fns` + `mono_queue` from codegen. Amend DESIGN.md §"Resolution and monomorphisation" to describe the pass as covering all `Type::Forall`-Defs. Tests: existing polymorphic fixtures (`poly_id`, `poly_apply`, `poly_rec_capture`) green; new fixture `cmp_max_smoke` proves cross-cutting (`cmp_max : forall a. Ord a => (a, a) -> a` at Int synthesises both `cmp_max__Int` and nested `compare__Int` in one fixpoint). |
| **23.5** (revised) | upcoming | **Prelude free fns + E2E.** Add `ne`/`lt`/`le`/`gt`/`ge` to `examples/prelude.ail.json`. E2E fixtures: (a) positive polymorphic helper at Int/Bool/Str, (b) negative — `eq f g` at Float typecheck-rejects with Float-aware diagnostic, (c) user-ADT — `IntBox` with `Eq`/`Ord` instances + polymorphic helper monomorphises to the user instance. Amend DESIGN.md §"Decision 11 / Prelude classes" — Eq/Ord shipped; the "Milestone 22 ships no built-in Prelude classes" wording stays as historical accuracy with a forward-pointing addendum. Roadmap: P1 Post-22 Prelude entry from `[~]` to `[x]` for Eq/Ord half; Show half stays. | | **23.5** (revised) | upcoming | **Prelude free fns + E2E.** Add `ne`/`lt`/`le`/`gt`/`ge` to `examples/prelude.ail.json`. E2E fixtures: (a) positive polymorphic helper at Int/Bool/Str, (b) negative — `eq f g` at Float typecheck-rejects with Float-aware diagnostic, (c) user-ADT — `IntBox` with `Eq`/`Ord` instances + polymorphic helper monomorphises to the user instance. Amend DESIGN.md §"Decision 11 / Prelude classes" — Eq/Ord shipped; the "Milestone 22 ships no built-in Prelude classes" wording stays as historical accuracy with a forward-pointing addendum. Roadmap: P1 Post-22 Prelude entry from `[~]` to `[x]` for Eq/Ord half; Show half stays. |
## Data flow ## Data flow
@@ -271,8 +255,8 @@ The milestone closes when:
1. **23.4 has landed:** `crates/ailang-check/src/mono.rs::monomorphise_workspace` 1. **23.4 has landed:** `crates/ailang-check/src/mono.rs::monomorphise_workspace`
synthesises both class-method and polymorphic-free-fn mono Defs synthesises both class-method and polymorphic-free-fn mono Defs
in one fixpoint loop. `crates/ailang-codegen/src/lib.rs::lower_polymorphic_call` + in one fixpoint loop. `crates/ailang-codegen/src/lib.rs::lower_polymorphic_call` +
`module_polymorphic_fns` + `mono_queue` are removed. Commits `module_polymorphic_fns` + `mono_queue` are removed. (prep2 +
`a06159d` (prep2) + `c42a0f5` (prep3) are rolled back. prep3 were never on main; no rollback step in scope.)
2. **DESIGN.md §"Resolution and monomorphisation" amended:** the 2. **DESIGN.md §"Resolution and monomorphisation" amended:** the
pass description covers all `Type::Forall`-quantified Defs, not pass description covers all `Type::Forall`-quantified Defs, not
only class methods. only class methods.
@@ -362,8 +346,6 @@ New under B1 unification:
`crates/ailang-codegen/src/lib.rs` (`lower_polymorphic_call`, `crates/ailang-codegen/src/lib.rs` (`lower_polymorphic_call`,
`module_polymorphic_fns` fields, `mono_queue` machinery). Net `module_polymorphic_fns` fields, `mono_queue` machinery). Net
code reduction expected. code reduction expected.
- **23.4 rollback:** `git revert a06159d c42a0f5` plus adaptation
to the newly-dead code paths in codegen, estimated 80 LOC.
- **23.5 prelude additions:** `examples/prelude.ail.json` +30-40 - **23.5 prelude additions:** `examples/prelude.ail.json` +30-40
lines (five free fns with Forall-constraint signatures and lines (five free fns with Forall-constraint signatures and
bodies). Three new E2E `.ail.json` fixtures, ~60 lines JSON. bodies). Three new E2E `.ail.json` fixtures, ~60 lines JSON.
@@ -394,14 +376,19 @@ relies on as currently-true.
corresponding workspace Defs. corresponding workspace Defs.
4. `examples/prelude.ail.json` today contains no free fns (only 4. `examples/prelude.ail.json` today contains no free fns (only
ADT, classes, instances). ADT, classes, instances).
5. Commits `a06159d` (prep2) and `c42a0f5` (prep3) added codegen 5. prep2 and prep3 (the codegen bare-name fall-through patches)
bare-name fall-throughs that were anticipatory patches for the *never reached main*. They lived on the stranded iter/23.4
prelude free fns; they have no currently-active load-bearing branch which was deleted on 2026-05-11. The current main
case outside the still-not-shipped 23.4 free fns. contains no codegen bare-name fall-through for polymorphic
6. Commit `8d39f13` (prep.1, linearity) and commit `aef4ab8` free-fn calls — codegen rejects bare polymorphic free-fn calls
(prep.2, check bare-name) operate at typecheck / linearity time today, which is exactly what makes the original iter-23.4 BLOCK.
— before any mono pass — and are load-bearing for any prelude 6. Commits on main `0caaced` (prep.1, linearity registers `Def::Class`
free-fn resolution regardless of mono architecture. method types in globals) and `923dd8c` (prep.2, check bare-name
fall-through to implicit-imported free fns) operate at
typecheck / linearity time — before any mono pass — and are
load-bearing for any prelude free-fn resolution regardless of
mono architecture. (Originals from stranded branch: `8d39f13`
and `aef4ab8`; cherry-picked onto main 2026-05-11.)
7. `crates/ailang-codegen/src/lib.rs::lower_polymorphic_call` is 7. `crates/ailang-codegen/src/lib.rs::lower_polymorphic_call` is
invoked from two call sites today (lines 1944, 1972), both of invoked from two call sites today (lines 1944, 1972), both of
which become direct mono-symbol calls after 23.4. which become direct mono-symbol calls after 23.4.