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:
20
test/wcc/data/enum_union_tag/case.ww
Normal file
20
test/wcc/data/enum_union_tag/case.ww
Normal file
@@ -0,0 +1,20 @@
|
||||
//ww:run-exit 0
|
||||
// Two enums in one union: variant tags must resolve nominally. The
|
||||
// enum-blind typeeq matched ANY enum pair (wwstage widened shape.BALL
|
||||
// into the color variant, tag 0), and the post-order revisit clobbered
|
||||
// the folded member's enum stamp to untyped_int (first-variant
|
||||
// fallback). Both orderings pinned.
|
||||
package main;
|
||||
type color = enum { RED, GREEN };
|
||||
type shape = enum { BOX, BALL };
|
||||
type either = (color | shape);
|
||||
type either2 = (shape | color);
|
||||
export fn main() i32 = {
|
||||
let e: either = shape.BALL;
|
||||
if (!(e is shape)) { return 1; };
|
||||
let f: either2 = color.RED;
|
||||
if (!(f is color)) { return 2; };
|
||||
let g: either = color.GREEN;
|
||||
if (!(g is color)) { return 3; };
|
||||
return 0;
|
||||
};
|
||||
Reference in New Issue
Block a user