wwstage exprtype's N_CALL fn-value arm peeled ALL pointer levels before the TY_FN gate, so a deref-less `pf(21)` where pf:**fn type-checked and lowered -- then segfaulted at runtime (a silent miscompile). cstage peels exactly one level and loud-rejects (the C6a discipline, check.c:1947). Align wwstage DOWN: peel one level (loop -> if); a remaining non-TY_FN callee hits a loud "calling non-function" reject mirroring cstage's message. Both stages now reject the exotic deref-less `**fn`/`***fn` shape; the legitimate `(*pf)(21)` and one-level deref-less `f(21)` (f:*fn) still compile + run. Multi-level autoderef is a separate deferred FEATURE, not a miscompile to lower (rule 7/10 -- align the richer stage down to the leaner, no value ships). ww-only change (cstage is the correct oracle); a reject emits no asm, so the byte-id baselines and LANGBYTEID floor are unchanged. Pins: cfail test/wcc/data/fnptr_pp_derefless_reject (both stages reject, reddens-on-revert -- the silent miscompile resurfaces if the fix is reverted) + test/lang/fnptr_derefless_call_test (positive guard (*pf)(21)==42 and one-level f(21), value-asserted + byte-id, so the fix does not over-reject the legitimate one-level autoderef).
308 KiB
308 KiB