wcc: enums compare nominally; folded members keep their enum stamp
Two composing defects made a two-enum union mis-tag in wwstage (live cs!=ww: `let e: (color|shape) = shape.BALL` stored tag 0 — the color arm — while cstage stored 1). type_eq/typeeq had no TY_ENUM arm, so ANY two enums fell into the primitive default and compared equal; enums are nominal (harec: an enum IS its alias type) and now compare by node identity only. Underneath, the wwstage post-order revisit re-stamped the constant-folded enum member (an N_INTLIT) as untyped_int, clobbering the enum stamp the N_DOT fold applied, so the widen matcher fell to its first-variant fallback -- the #59.9 N_BIN guard now twins on N_INTLIT (cstage cexpr is single-pass and never clobbered).
This commit is contained in:
@@ -275,6 +275,15 @@ type_eq(Type *a, Type *b)
|
||||
}
|
||||
case TY_NAMED:
|
||||
return a == b; /* nominally equal only when same node */
|
||||
case TY_ENUM:
|
||||
/* Enums are nominal (harec: an enum IS its alias type):
|
||||
* distinct decls are distinct types even with identical
|
||||
* storage/members. Falling into the primitive default made
|
||||
* ANY two enums equal — the wwstage variant matcher picked
|
||||
* the first enum variant of a union for a value of the
|
||||
* OTHER enum (live cs!=ww, wrong tag at runtime). Same-decl
|
||||
* chased ends hit the a == b fast path above. */
|
||||
return 0;
|
||||
case TY_TUPLE: {
|
||||
Tparam *pa = a->params, *pb = b->params;
|
||||
while (pa && pb) {
|
||||
|
||||
Reference in New Issue
Block a user