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:
@@ -569,6 +569,13 @@ export fn typeeq(a: *tinfo, b: *tinfo) bool = {
|
||||
return true;
|
||||
};
|
||||
if (k == tykind.TY_NAMED) { return false; }; // nominal: only same ptr
|
||||
// Enums are nominal (harec: an enum IS its alias type): distinct
|
||||
// decls are distinct types even with identical storage/members.
|
||||
// Falling into the primitive tail made ANY two enums equal — the
|
||||
// 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.
|
||||
if (k == tykind.TY_ENUM) { return false; };
|
||||
if (k == tykind.TY_TAGGED) {
|
||||
// Structural: variant lists match position-by-position, and
|
||||
// the nullable `(*T|void)` fold is part of identity. Mirrors
|
||||
|
||||
Reference in New Issue
Block a user