Files
ww/selfhost/cmd/w6c
Hojun-Cho 56aac85f6f cgen: #95 c2 structural variant fallback — both-stage fused
A nominally-unrelated, structurally-equal NAMED source into a NAMED
variant (kb95_unrel: ta/tb same-layout structs, src ta -> (void|tb))
was LIVE both-wrong-identical byte-id silent: both checkers accept,
both cgens tagged 0. After c1's chain arm finds no shared chain
node, match the variant whose CHASED type type_eq's/typeeq's the
source's chased bottom — chased type EQUALITY only, no
type_is_assignable scalar import, no int widening (ken's binding
scalar warning). Same NAMED-source branch, both stages
(cg_tag_for_variant / flatvariantidxt), forced fuse.

Correctness reference, cite 1 — harec tagged_select_subtype P2+P3
(ref/harec/src/types.c:702-739), verbatim:

	if (t->id == subtype->id) {
		return t;
	}
	if (type_is_assignable(ctx, t, subtype)) {
		selected = t;
		++nassign;
	}
	...
	if (nassign == 1) {
		return selected;
	}
	return NULL;

with type_is_assignable's non-tagged path dealiasing both sides and
accepting composites only via interned pointer equality
(types.c:988-1002), verbatim:

	if (type_dealias(ctx, to)->storage != STORAGE_TAGGED) {
		to = type_dealias(ctx, to);
		from = type_dealias(ctx, from);
	}
	...
	if (to == from && to->storage != STORAGE_VOID) {
		return true;
	}

Cite 2 — type_hash interns bare composites STRUCTURALLY (banked as
types.c:72-81; verified in the vendored copy at types.c:444 +
struct/union arm :514-525), verbatim:

	case STORAGE_UNION:
		hash = fnv1a_size(hash, type->struct_union.packed);
		for (const struct struct_field *field = type->struct_union.fields;
				field; field = field->next) {
			if (field->name) {
				hash = fnv1a_s(hash, field->name);
			}
			hash = fnv1a_u32(hash, type_hash(field->type));
			hash = fnv1a_size(hash, field->offset);
		}

— no decl ident in the hash, so harec's two decls dealias to ONE
interned node and `to == from` holds: acceptance is DEFINITIONAL
under interning, not an arm whose text could be misread. Our store
does not intern; chased type equality is the non-interned rendering
of the same rule.

Honest divergence (the >=2-structural-match hard-error STAYS): under
harec's interning two structurally-identical variants are ONE type —
a union cannot contain it twice — so the ambiguity case is
unrepresentable there; our hard-error (twin texts, shared tail
"source structurally matches >=2 variants — ambiguous without
nominal layout (#95)") is the correct nominal-lossy-model rendering,
not a harec deviation.

Pin table: unrel_struct row added (kb95_unrel graduates ok/1-ok/1 ->
0/0, byte-id held) — suite now 48/48. All c1 rows unmoved.

Invariants: 163-row dissolution matrix at tip — same 3 family
graduations as c1, ZERO new movers; five mains cs-vs-ww byte-id OK;
make all 0; sizelint 0; peellint 0 (no new peel sites — the
structural leg reads only chased ends); all 944 suites + 808 green.
w6c_ww/wwdump_ww main.combined.ww regen'd.
2026-06-06 07:43:39 +09:00
..