wcc: accept NAMED-variant nominal match at tagged→tagged subset (#205)
The tagged→tagged subset arm walked src's leaves against dst's flat variant list, so `let r: (size | eof | wrapper) = e` with e: wrapper REJECTED at cstage's checker — wrapper's leaves (unsupported, underread, nomem) aren't direct variants of dst. Wwstage's permissive tail accepted silently but cgen then miscompiled the tag (#199b layout- extension family, deferred). Mirror the concrete→tagged fix from #199 (α) at type.c:316: when src is a NAMED-tagged wrapper and dst has a direct NAMED-tagged variant equal to src, accept by nominal identity BEFORE the subset loop. Wwstage's isassignable mirrors the structural insertion before the existing `*confident = false; return true;` tail (deferred-tightening per #202). SSoT with `is`/`as` non-recursive variant lookup (#198 family). Cgen's tag-remap for the wrapper-as-whole case still maps src variants to dst tag 0 — the wrapped-slot layout for `dst.tag = variant_idx, dst.payload = src` is #199b future-work. Probe verifies checker-accept + runtime exit-clean only; does NOT inspect the resulting variant tag. Probe 774_tagged_widen_named_variant.c covers 5 rows: bug-repro, nested-wrapper, pure-leaf subset (regression), concrete-unrelated rejection (gate), branched callee. Two sibling cgen/checker bugs surfaced (wwstage cgwidentaggedstorebp ssz<slot_sz pad gap; wwstage isassignable !void-alias collapse) and documented inline at the probe-row comment, kept in #202 family.
This commit is contained in:
@@ -326,6 +326,20 @@ type_assignable(Type *dst, Type *src)
|
||||
}
|
||||
if (du && du->kind == TY_TAGGED &&
|
||||
su && su->kind == TY_TAGGED) {
|
||||
/* #205: NAMED-variant nominal compare BEFORE subset.
|
||||
* Mirror of the concrete→tagged arm at :316-324 (#199 α).
|
||||
* When src is a NAMED-tagged wrapper and dst has a direct
|
||||
* NAMED-tagged variant equal to src, accept by nominal
|
||||
* identity without recursing into src's variants — those
|
||||
* are wrapper's leaves, not direct variants of dst, so
|
||||
* the subset loop below would reject. SSoT with `is`/`as`
|
||||
* variant lookup (#198 family). */
|
||||
for (Tparam *dp = du->params; dp; dp = dp->next) {
|
||||
Type *pu = (dp->type && dp->type->kind == TY_NAMED)
|
||||
? dp->type->under : dp->type;
|
||||
if (pu && pu->kind == TY_TAGGED &&
|
||||
type_eq(dp->type, src)) return 1;
|
||||
}
|
||||
for (Tparam *sp = su->params; sp; sp = sp->next) {
|
||||
int ok = 0;
|
||||
for (Tparam *dp = du->params; dp; dp = dp->next)
|
||||
|
||||
Reference in New Issue
Block a user