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.
This commit is contained in:
@@ -921,6 +921,33 @@ cg_tag_for_variant(Type *t, Type *vt)
|
||||
fatal("cg_tag_for_variant: source alias chain "
|
||||
"reaches >=2 variants — ambiguous without "
|
||||
"nominal layout (#95)");
|
||||
if (found >= 0) return found;
|
||||
/* c2 (#95): no chain hit (found/n are still -1/0 here) —
|
||||
* structural fallback on the chased ends. harec interns
|
||||
* bare composites structurally (type_hash, ref/harec/src/
|
||||
* types.c:72-81), so a nominally-unrelated structurally-
|
||||
* equal decl DEALIASES TO THE SAME NODE there and the
|
||||
* assignability arm accepts via `to == from`
|
||||
* (types.c:1000-1002) — acceptance is definitional, not an
|
||||
* arm we could misread. Our store does not intern, so the
|
||||
* pointer compare of pass 1b misses it; chased type_eq is
|
||||
* the non-interned rendering of the same rule. EQUALITY
|
||||
* only — no type_is_assignable scalar import. The >=2
|
||||
* hard-error is the nominal-lossy-model rendering of a case
|
||||
* harec cannot represent (two structurally-identical
|
||||
* variants intern to ONE type — a union cannot contain it
|
||||
* twice), not a harec deviation. */
|
||||
idx = 0;
|
||||
for (Tparam *p = t->params; p; p = p->next, idx++) {
|
||||
if (p->type && type_eq(type_chase_named(p->type), sb)) {
|
||||
if (found < 0) found = idx;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if (n >= 2)
|
||||
fatal("cg_tag_for_variant: source structurally "
|
||||
"matches >=2 variants — ambiguous without "
|
||||
"nominal layout (#95)");
|
||||
return found;
|
||||
}
|
||||
/* Pass 2 (#15): no exact variant matched — try a structural match of
|
||||
|
||||
Reference in New Issue
Block a user