wwstage: reject error-type vs int comparison (#246)
cstage cbinop routes every comparison through unify_arith (cmd/wcc/check.c:952), which loud-rejects an error-typed operand paired with a differing type (e.g. strconv.invalid != i32). wwstage binoptype returned bool for comparisons without any unify step, so it silently accepted a program cstage rejects -- a rule-10 break (align the leaner-but-leniner wwstage DOWN to cstage). Scope the rejection to an error operand (varianterr) mismatched with the other (typeeqast) so the broad differing-types diagnostic -- whose typeeqast-vs-cstage-type_eq asymmetry risk could reject valid bootstrap code -- stays out of wwstage. Covers the whole comparison family (EQ/NEQ/LT/LE/GT/GE), all of which cstage routes through unify_arith. Found by impl-strconv3 writing the strconv test. Gate-blind: the bootstrap never compares an error type to an int, so byte-id stayed green while the stages disagreed on what's a valid program. test/wcc/949_errtype_compare.c: both drivers reject invalid !=/==/< i32 (K_BUILDERR); same-error-type and plain-int compares still accept on both stages + cs==ww byte-id (K_RUN). 12/12.
This commit is contained in:
@@ -12384,8 +12384,23 @@ fn binoptype(c: *checker, e: *node) *node = {
|
||||
};
|
||||
if (op == tkind.TK_EQ || op == tkind.TK_NEQ ||
|
||||
op == tkind.TK_LT || op == tkind.TK_LE ||
|
||||
op == tkind.TK_GT || op == tkind.TK_GE ||
|
||||
op == tkind.TK_AND || op == tkind.TK_OR) {
|
||||
op == tkind.TK_GT || op == tkind.TK_GE) {
|
||||
// cstage routes every comparison through unify_arith (check.c:952/
|
||||
// 955 cbinop), which loud-rejects an error-typed operand paired
|
||||
// with a differing type, e.g. strconv.invalid != i32. wwstage's
|
||||
// unifyarith stays silent on generic typed mismatches (5-lite-b),
|
||||
// but the error-type case is a real cs!=ww edge and must reject to
|
||||
// match cstage (#246, rule 10). Scoped to error operands so the
|
||||
// broad differing-types flip (typeeqast vs cstage type_eq
|
||||
// asymmetry risk) stays out.
|
||||
if (varianterr(c, ltn) || varianterr(c, rtn)) {
|
||||
if (!typeeqast(ltn, rtn)) {
|
||||
deffolderr(c, e, "operands have differing types");
|
||||
};
|
||||
};
|
||||
return mktname(c, "bool");
|
||||
};
|
||||
if (op == tkind.TK_AND || op == tkind.TK_OR) {
|
||||
return mktname(c, "bool");
|
||||
};
|
||||
// Unreachable for valid input: op is one of TK_PLUS/MINUS/STAR/
|
||||
|
||||
Reference in New Issue
Block a user