wcc: general call-arg typecheck via assignability union, both stages

wwstage's desugarcallargs ran no general per-arg typecheck (only the
narrow #258 array-to-slice arm): any mistyped scalar call-arg silently
miscompiled (int read as a 24B slice header; the -T face was a user
const __wwtests building a garbage test binary). Route every call-arg
through the predicate union isassignable()||assignableaddrfn(),
mirroring cstage type_assignable||assignable_addrfn and the check.c:1869
diagnostic. Confident scalar/aggregate and aggregate/aggregate
kind-mismatch rejects live in shared isassignable; the concrete-to-
tagged arm is shape-matched-lenient via tagshape() (AST mirror of cgen
taggedvariantindext) so genuine variant members keep flowing while
shape-mismatched aggregates reject. Reserve __wwtests under -T in both
stages (mirror the main reservation, check.c:2996). New table-driven
989_callarg_typecheck, 31 fixtures, reject rows proven red on pre-fix
binaries.

Deferred, filed, site-commented: the assign seam rides #178->#36
(typeeqast cannot compare variadic/module-qualified fn sigs); the
same-coarse-shape same-leaf nominal collision over-accept rides #37
(#10/#66 — the distinguishing module is absent from the AST surface
isassignable operates on).
This commit is contained in:
2026-06-11 20:45:02 +09:00
parent 8d2d157a58
commit 556a65ee86
6 changed files with 1291 additions and 45 deletions

View File

@@ -2999,6 +2999,16 @@ check_file(Checker *c, Node *file)
&& strcmp(d->str, "main") == 0 && d->body != NULL)
err(c, d->pos, "test mode: main is synthesized "
"by -T; remove the explicit main");
/* #24(b): the synth table OWNS `__wwtests` — loud-reject a user
* decl of that name (twin of the `main` reservation above). A user
* __wwtests whose type happens to match run()'s [](str,*fn()void)
* param slips the general call-arg check but still silently shadows
* the synth table; reserve the NAME so the collision is loud
* regardless of type. Any decl kind. */
for (Node *d = file->list; d; d = d->next)
if (d->str && strcmp(d->str, "__wwtests") == 0)
err(c, d->pos, "test mode: __wwtests is reserved "
"by -T; rename the declaration");
/* (c) collect @test fns in file->list order; build one table row
* `("<name>", &<name>)` per validated @test fn. */
Node *rhead = NULL, *rtail = NULL;