wcc+w6c_ww: loud-gate try-propagation over multi-success unions (F8/F9 interim)
? and ! assume ONE success member end-to-end: the checker collapses the result to the first non-error variant (check.c tagged_success_type / check.ww exprtype) and cgen emits a single tag compare, so any other success member is silently mistaken for an error — ? propagates it to the caller (p11h: []capture read back as nomem, exit 21), ! aborts on it. Until the honest subset-union result typing lands (task #14, harec check.c:2759-2835), both stages loud-reject |success| > 1 at the checker choke-points (one per stage), identical diagnostic, both ops per rob's one-class ruling (#133 precedent). (T|err1|err2) — one success, many errors — stays legal (925 canary + new accept rows). F9 rides along (task #12): wwstage scruttype only resolves IDENT/DOT, so the direct forms f()? is T / match(f()?) / f()! is T slipped its lenient-miss contract and were silently ACCEPTED where cstage rejects (cs!=ww, gate-blind). checkisas/checkmatchexhaust now resolve the try-result via exprtype, keyed on the RESOLVED success type — a named tagged success ((ab|nomem)? is i32) keeps being accepted, matching cstage's verdict empirically. test/wcc/806: 11 rows x dual driver + byte-id accepts (26 fixtures); reject rows pin exact per-stage diagnostic text; p11h + q_card2_unw graduated to rejects; call-arg-position reject + void-success accept pin position-independence and the dominant lib/ (void|err)? shape. Tasks #5 + #12; #14 lifts both gates together.
This commit is contained in:
@@ -1887,11 +1887,26 @@ cexpr(Checker *c, Node *n)
|
||||
* (so the caller can match on it). cgen does the tag remap.
|
||||
* For ! : no propagation, so no subset check. */
|
||||
Type *succ = tagged_success_type(u);
|
||||
int has_errors = 0;
|
||||
for (Tparam *p = u->params; p; p = p->next)
|
||||
if (tagged_is_error_variant(u, p->type)) {
|
||||
has_errors = 1; break;
|
||||
}
|
||||
int has_errors = 0, nsucc = 0;
|
||||
for (Tparam *p = u->params; p; p = p->next) {
|
||||
if (tagged_is_error_variant(u, p->type))
|
||||
has_errors = 1;
|
||||
else
|
||||
nsucc++;
|
||||
}
|
||||
/* F8 interim gate (task #5): try-propagation assumes ONE
|
||||
* success member end-to-end — succ collapses to the first
|
||||
* non-error variant and cgen emits a single tag compare, so
|
||||
* any OTHER success member is silently mistaken for an error
|
||||
* (? propagates it; ! aborts on it). One class, both ops
|
||||
* (#133 precedent). Until the honest subset-union result
|
||||
* typing lands (task #14, harec check.c:2759-2835), reject
|
||||
* loud. */
|
||||
if (nsucc > 1) {
|
||||
return n->type = err(c, n->pos,
|
||||
"%s: multi-success union unwired (task #14): bind and match instead",
|
||||
n->kind == N_TRYPROP ? "?" : "!");
|
||||
}
|
||||
if (n->kind == N_TRYPROP && has_errors) {
|
||||
Type *r = c->ret;
|
||||
Type *ru = (r && r->kind == TY_NAMED) ? r->under : r;
|
||||
|
||||
Reference in New Issue
Block a user