w6c+wwstage: tag a bare value widened into a NAMED-alias union variant via structural fallback (#15)

Variant selection (cg_tag_for_variant / flatvariantidxt) matched union variants by exact type only, so widening a bare value (e.g. *vtable) into a union with a NAMED ptr-alias variant (stream = *vtable, in handle = (file | stream)) found no match and the tag defaulted to 0 -- the wrong variant. In the compiler this hit emitbytes' io.write(&cgoutstream.vt) once io.write took a handle, writing the asm to a garbage fd -> empty .s -> w6c_ww miscompiled everything. Add a second selection pass: when the exact pass finds no variant, structurally compare the bare source against each NAMED-alias variant's unwrapped type; exact-match still wins in pass 1 (so a bare i64 stays the i64 variant, not oserror=!i64, which kept the os/errno union building). A >=2-structural-match collision guard (extending #218's) hard-errors LOUDLY on genuine nominal ambiguity (two ptr-aliases to the same struct) instead of silently first-picking, citing #199b/#10. Symmetric across cstage (cmd/w6c/cgen.c) and wwstage (selfhost/cmd/wcc/cgenutil.ww). One-level NAMED unwrap (chained ptr-aliases unmatched, unexercised -> #17). Adds test/wcc/789 (positive widen byte-id+runtime + degenerate-ambiguity reject guard, both stages). Unblocks post-eFinal #5's handle surface. rule-10 fix-up.
This commit is contained in:
2026-05-30 09:04:33 +09:00
parent 419c896ad0
commit 45e5d74047
6 changed files with 453 additions and 0 deletions

View File

@@ -337,6 +337,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
$(BIN)/test_amp_fn_assign_run \
$(BIN)/test_xmod_alias_struct_collide_run \
$(BIN)/test_xmod_variant_match \
$(BIN)/test_named_ptr_alias_variant_widen \
$(BIN)/test_structvariant_largeunion_return \
$(BIN)/test_narrow_alias_deref_store \
$(BIN)/test_bufio_vstream_run \
@@ -755,6 +756,16 @@ $(BIN)/test_xmod_variant_match: test/wcc/787_xmod_variant_match.c \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
# #15: widening a bare *vtable into a NAMED-alias variant (`stream` =
# *vtable) of `(file | stream)` must compute the right tag, not default
# to tag 0. Both-stage byte-id + runtime, plus a degenerate-ambiguity
# reject row (drew's >=2 guard). Self-contained single-file probes.
$(BIN)/test_named_ptr_alias_variant_widen: test/wcc/789_named_ptr_alias_variant_widen.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
# #9: returning a STRUCT variant of a LARGE (>4-eightbyte) tagged union.
# Both-stage byte-id + runtime (reads tag AND the widened &fn field, so a
# dropped-store regression can't hide behind self-consistent byte-id).