check: type the N_BIN operand of as in the wwstage

An enum OR-fold under `as` ((m.A|m.B) as u32) was never typed:
scruttype resolves IDENT/DOT only, and the post-order restamp then
re-derived the folded member literals as untyped_int. The unstamped
operand missed cgtypeassert's #27b enum-reinterpret gate and lowered
as a phantom tagged assert — unconditional exit 1 at runtime on the
wwstage leg. checkisas now types an N_BIN lhs and the N_BIN restamp
preserves an existing enum stamp. Graduates the #59.9 stattest pin.
This commit is contained in:
2026-08-08 00:59:02 +09:00
parent c421c2b20a
commit 125f626697
4 changed files with 51 additions and 5 deletions

View File

@@ -3328,6 +3328,22 @@ fn exprtype(c: *checker, e: *syntax.node, hint: *syntax.node) *syntax.node = {
};
if (k == syntax.nkind.N_BIN) {
let tn: *syntax.node = binoptype(c, e);
// #59.9: checkisas pre-stamps an enum OR-fold (`(m.A|m.B) as
// u32`) TY_ENUM and folds the member N_DOTs to int literals;
// this post-order revisit re-derives from those now-untyped
// literals and clobbered the stamp, so cgtypeassert's #27b
// reinterpret gate missed and emitted a phantom tagged assert
// (unconditional exit 1). Keep an existing enum stamp; the
// returned tnode contract for callers is unchanged.
let pre599: *syntax.tinfo = e.type_: *syntax.tinfo;
if (pre599 != nil) {
let prech: *syntax.tinfo = tichase(pre599);
if (prech != nil) {
if (prech.kind == syntax.tykind.TY_ENUM) {
return tn;
};
};
};
e.type_ = tinfofornode(c, tn): *void;
return tn;
};
@@ -6353,6 +6369,15 @@ fn checkisas(c: *checker, n: *syntax.node) void = {
if (n.lhs.kind == syntax.nkind.N_TRYPROP || n.lhs.kind == syntax.nkind.N_TRYUNW) {
st = exprtype(c, n.lhs, nil);
};
// #59.9: an N_BIN operand (`(m.A | m.B) as u32`) was never
// typed, so the OR-fold reached cgen unstamped and
// cgtypeassert's enum-reinterpret gate (#27b) missed —
// lowering a plain enum value as a phantom tagged assert
// (unconditional exit 1). cstage types the lhs
// unconditionally (cmd/wcc/check.c:2220 cexpr(c, n->lhs)).
if (n.lhs.kind == syntax.nkind.N_BIN) {
st = exprtype(c, n.lhs, nil);
};
};
let u: *syntax.node = resolvealias(c, unwrapbang(st));
if (u == nil) { return; };