docs(ffi-linkage): checkpoint — extern C-variadic prereq DONE; both fn-path prereqs cleared
Next step is the fn-decl #foreign body-marker migration onto extern (behavior-preserving single refactor commit; lowering + both prereq gates already coalesce is_foreign with extern_export).
This commit is contained in:
@@ -5,8 +5,20 @@ Companion to `current/PLAN-EXTERN-EXPORT.md` — one merged plan: **Part A** add
|
||||
every commit, one step at a time per the cadence rule.
|
||||
|
||||
## Last completed step
|
||||
**Phase 5.0 prereq — visibility-gate equivalence** (xfail `717c35d` → fix
|
||||
`7d8ba1a`) — the first of the two deferred fn-path prerequisites is now LOCKED.
|
||||
**Phase 5.0 prereq — extern C-variadic tail** (xfail `9a2c78d` → fix `0fdc821`) —
|
||||
the SECOND (and last) deferred fn-path prerequisite. **BOTH fn-path prereqs now
|
||||
done.** The C-variadic `...` handling was keyed on the `#foreign` (`foreign_expr`)
|
||||
body shape at two sites — the `is_variadic` drop in `declareFunction`
|
||||
(`decl.zig:2097`) and the call-site early-out in `packVariadicCallArgs`
|
||||
(`pack.zig:302`). A variadic `extern` therefore kept its trailing slice param and
|
||||
slice-packed the extras → garbage at the C ABI (probe: `sum_ints(3,10,20,30)` →
|
||||
53316585, not 60). Both gates now also fire for `extern_export == .extern_`, so a
|
||||
variadic `extern` drops the `..args: []T`, sets `is_variadic`, and passes extras
|
||||
through the C `...` slot with default argument promotion — byte-identical to its
|
||||
`#foreign` twin. New example **1229** (`1229-ffi-extern-cvariadic`, JIT `#source`,
|
||||
int-sum + double-avg). Suite green (645 corpus / 444 unit, 0 failed).
|
||||
|
||||
### Prior: Phase 5.0 prereq — visibility-gate equivalence (xfail `717c35d` → fix `7d8ba1a`) — the first of the two deferred fn-path prerequisites.
|
||||
The non-transitive C-import visibility gate (`isVisible(.c_import_bare)`,
|
||||
`decl.zig:2249`) used to recognise only the legacy `#foreign` body shape; a bare
|
||||
`extern` fn (empty-block body + `extern_export == .extern_`) escaped the gate via
|
||||
@@ -99,15 +111,32 @@ AOT), 1227 (export fn rename, AOT), 1348 (objc extern class), 1349 (objc export
|
||||
(jni extern class), 1174/1175 (interplay diagnostics).
|
||||
|
||||
## Next step
|
||||
**PART B — Phase 5.0, fn-path variadic prerequisite** (the SECOND of the two
|
||||
deferred fn-path prereqs; visibility-gate equivalence is now DONE). The
|
||||
`is_variadic` drop in `declareFunction` is gated on `is_foreign` only, so a
|
||||
migrated variadic `extern` (e.g. `printf`) would lose its `...` tail. Extend the
|
||||
gate to cover `extern_export == .extern_`. Cadence: xfail an `extern` variadic fn
|
||||
losing its `...` (locks the gap), then the next commit fixes the gate. Find the
|
||||
exact site via `grep -n "is_variadic" src/ir/lower/decl.zig` (the checkpoint's old
|
||||
`decl.zig:2097` line ref may have drifted). AFTER both prereqs land, the fn-decl
|
||||
`#foreign` body-marker path (`parser.zig:~2062`) can migrate onto `extern`.
|
||||
**PART B — Phase 5.0, fn-decl `#foreign` body-marker migration** (BOTH prereqs —
|
||||
visibility-gate + variadic — are now DONE). Route the fn-decl `#foreign` path so a
|
||||
`#foreign` fn builds the SAME extern AST that postfix `extern` already produces,
|
||||
instead of a `foreign_expr` body. This is the highest-value path (the bulk of
|
||||
`#foreign` usage). Key sub-questions to resolve before/while routing:
|
||||
- The `foreign_expr` node carries `library_ref` + `c_name`; the `extern` fn carries
|
||||
`extern_export = .extern_` + `extern_lib` + `extern_name` on the FnDecl with an
|
||||
empty-block body. Migration = the parser's fn-body `#foreign` arm
|
||||
(`parser.zig:~2062`) builds the extern shape (set `extern_export`, map
|
||||
`library_ref→extern_lib`, `c_name→extern_name`) rather than a `foreign_expr`.
|
||||
- Lowering ALREADY coalesces the two at every fn site checked this stream
|
||||
(`decl.zig` 2088/2124/2132/2156/2324/2531 read `is_foreign OR extern_export`),
|
||||
and the two prereq gates (visibility `decl.zig:2249`, variadic `decl.zig:2097` +
|
||||
`pack.zig:302`) now do too — so the migration should be behavior-preserving with
|
||||
ZERO snapshot churn. VERIFY with the A→B gate test (`lower.test.zig`) + a full
|
||||
`zig build test` after routing; any churn means a site still reads `foreign_expr`
|
||||
structurally and must be coalesced first.
|
||||
- ⚠ This ALSO migrates the **const-with-type** path implicitly IF it shares the same
|
||||
`foreign_expr`→extern reshape (it builds `const_decl{value=foreign_expr}`). Decide:
|
||||
reshape the const path's value node alongside, or leave the dead const path on
|
||||
`foreign_expr` until Phase 8 cutover. The const path is dead (see findings below),
|
||||
so leaving it is acceptable; but the parser arm is shared-ish — check whether the
|
||||
fn-body arm change touches it.
|
||||
- Cadence: because the migration is behavior-preserving (no churn), it's a single
|
||||
`refactor`/lock commit (like the 5.0 global-path commit `e5ddfbe`), NOT an
|
||||
xfail→fix pair.
|
||||
|
||||
**Investigation findings (this session — reorder the remaining paths):**
|
||||
- **const-with-type** (`parser.zig:316`, `name :: type_expr #foreign …`) is a
|
||||
@@ -174,6 +203,16 @@ Part A ratified (bare / postfix / `⇒ callconv(.c)` / lib-separate). Part B:
|
||||
NOT confirm this at the Part A milestone; confirm before Phase 9.
|
||||
|
||||
## Log
|
||||
- (5.0 prereq variadic xfail) Added `1229-ffi-extern-cvariadic` (JIT `#source`,
|
||||
int-sum + double-avg, `extern` C-variadic). Expected snapshot pins the DESIRED
|
||||
correct output. RED (variadic `extern` slice-packs extras → garbage:
|
||||
`sum_ints(3,10,20,30)` → 53316585; doubles → 0.0). `test`/xfail `9a2c78d`.
|
||||
- (5.0 prereq variadic fix) Extended the two C-variadic gates — the `is_variadic`
|
||||
drop in `declareFunction` (`decl.zig:2097`) and the early-out in
|
||||
`packVariadicCallArgs` (`pack.zig:302`) — to fire for `extern_export == .extern_`
|
||||
as well as a `foreign_expr` body. 1229 green (`60` / `2.000000`). Suite green
|
||||
(645 corpus / 444 unit, 0 failed). `fix`/green `0fdc821`. **BOTH fn-path prereqs
|
||||
DONE → fn-decl `#foreign` body-marker migration unblocked.**
|
||||
- (5.0 prereq vis xfail) Added cross-module example `1228-ffi-extern-c-non-transitive`
|
||||
(main → b → c). Main references c's lib-less `#foreign` + `extern` twins
|
||||
transitively; expected snapshot pins the DESIRED equivalent C-specific
|
||||
|
||||
Reference in New Issue
Block a user