Additive: keeps lib/io/io.ww's pre-vtable `stream` struct + `read`/`write`/`close` wrappers (fold-e2-eN migrates the legacy surface to vtable-backed implementations and retires it). lib/io/stream.ww — vtable struct (reader/writer/closer slots, spelled `(*T | void)` per #192 — ww parser rejects `nullable *T`), vstream = *vtable, and the st_read/st_write/st_close dispatchers per ref/hare/io/stream.ha:33-68. Void-arm `return e;` chains two direct widens: concrete `errors.unsupported` → `error` (#199 α) then `error` → (size|eof|error) (#205 NAMED-variant nominal at tagged→tagged subset). Hare's `?`-propagating st_close collapses to a direct `return (*c)(s);` because #173 is still open; the surface stays Hare-shaped. lib/io/types.ww — retarget reader/writer/closer fn-aliases from *stream to vstream. Extend `error` union to include `errors.unsupported` explicitly (no spread — per ken's #204-block the wrapper-vs-flatten layout asymmetry would mis-widen; the deferred fix is filed as #199b layout-extension). test/wcc/775_io_vtable_run.c — 7-row sentinel: reader/writer/ closer × {set, void} happy paths + branched-callee runtime. Rows verify the call runs + the constant exit; the void-arm rows do NOT inspect the resulting variant tag (deferred #199b wrapped-slot tag-remap mis-routes to dst tag 0). Cstage and wwstage emit byte-identical asm on every row. test/wcc/768_io_types_run.c — track the alias retarget; rows now build a vtable, pass `&vt` (= vstream), and call through the fn-VALUE param shape. Combined.ww regen for w6c + wwdump per #110: lib/errors lands transitively via the new `import errors;` in types.ww. Sibling filed inline (NOT fixed): the checker rejects bare `&fn_name` / `let p: *alias = &fn` assignment to a `(*alias | void)` field — the structural `*fn(...)` value isn't accepted as the `*alias` NAMED variant. Both stages reject. Probes route around via explicit `(&fn): *io.reader` cast at each vtable-field assignment.
58 KiB
58 KiB