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:
@@ -3418,6 +3418,22 @@ fn exprtype(c: *checker, e: *syntax.node, hint: *syntax.node) *syntax.node = {
|
||||
};
|
||||
};
|
||||
let tn: *syntax.node = mktname(c, "untyped_int");
|
||||
// #59.9 twin: a constant-folded enum member is an N_INTLIT
|
||||
// whose stamp carries the ENUM type; the post-order revisit
|
||||
// re-derived untyped_int and clobbered it, sending the
|
||||
// widen-store variant matcher to its first-variant fallback
|
||||
// (wrong tag, live cs!=ww — cstage cexpr is single-pass and
|
||||
// keeps the enum). Keep an existing enum stamp; the returned
|
||||
// tnode contract for callers is unchanged.
|
||||
let pre: *syntax.tinfo = e.type_: *syntax.tinfo;
|
||||
if (pre != nil) {
|
||||
let prech: *syntax.tinfo = tichase(pre);
|
||||
if (prech != nil) {
|
||||
if (prech.kind == syntax.tykind.TY_ENUM) {
|
||||
return tn;
|
||||
};
|
||||
};
|
||||
};
|
||||
e.type_ = tinfofornode(c, tn): *void;
|
||||
return tn;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user