wcc/ww: don't interface-check the sep-build root unit (BUG-1, #69)

The --sep producer compiled the ROOT build-target with the .wwi-producer
-I flag, so check_exported_type ran on the root and rejected a real-tool
root's legitimate `export fn f(a: *t)` over an unexported local type t
(the root is terminal — its interface is never imported, and its .wwi is
never consumed). The combined build never passes -I, so it built fine.
For pi==root, invoke w6c with -c -o only, no -I. Both stages (the wwstage
twin builds the shorter root argv). Gates that asserted __root.wwi exists
encoded the buggy behavior; updated to assert __root.s (the consumed
product) while deps' .wwi byte-id is retained.

M3-tail commit-6 prerequisite. Gate 989_seproot_export_run reproduces the
export-fn-over-unexported-type root + proves it sep-builds, with a
non-vacuity leg that the forced -I path still rejects.
This commit is contained in:
2026-06-16 17:16:37 +09:00
parent 747475174a
commit 2ff54c8bd4
7 changed files with 362 additions and 26 deletions

View File

@@ -1225,8 +1225,19 @@ build_one_sep(const char *src, int entry_is_dir, const char *out,
if (!fresh) {
if (sep_compose_unit(g, pi, scratch, order, norder, srcdir,
unitf) < 0) { free(order); free(g); return 1; }
snprintf(cmd, sizeof cmd, "%s -c -I %s -o %s %s",
c6, wwi, asmf, unitf);
/* BUG-1 (#69): -I <wwi> is purely the root's UNUSED
* `.wwi` output path, but it triggers wwi_emit →
* check_exported_type on the root. A terminal binary's
* root legitimately has `export fn` over an unexported
* LOCAL type (the root is never imported), which the
* export-check rejects. Skip -I for the root; its `.wwi`
* is never consumed. */
if (pi == root)
snprintf(cmd, sizeof cmd, "%s -c -o %s %s",
c6, asmf, unitf);
else
snprintf(cmd, sizeof cmd, "%s -c -I %s -o %s %s",
c6, wwi, asmf, unitf);
if (run(cmd) != 0) {
fprintf(stderr, "ww --sep: w6c failed for %s\n",
g->pkg[pi].path[0] ? g->pkg[pi].path : "(root)");