cgen: #95 c1 chain-membership variant arm — both-stage fused
A NAMED struct source that was not pointer-identical to a NAMED variant fell through every pass of cg_tag_for_variant (cmd/w6c/ cgen.c) / flatvariantidxt (selfhost/cmd/wcc/cgenutil.ww) and the widen stored tag 0 — both stages, byte-identical, gate-blind: wrong tag on VALID code at any alias depth, in both chain directions (.ai/ken-95-oracle.md §2: kb5_v2s1i, kb95_2lvl_i, kb95_deep_src, kb95_deep_var all both-wrong-identical at base). New pass 1b, identical both stages (the same route — forced fuse): after pass-1 exact (unchanged, FIRST — the (str|linerr) protection, harec's P1 short-circuit), a NAMED source matches the variant whose NAMED chain shares a pointer-identical node with the source's chain (an alias IS-A its base through the chain). Two linear NAMED chains intersect iff they share their chased bottom node (ken §1), so the walk is implemented as pointer identity of the chased ends through type_chase_named/tichase — the blessed chase choke-point. NO raw .under/->under hops were added, so the anticipated `peel-ok: nominal chain walk (#95)` annotations are unnecessary and the peellint whitelist is UNCHANGED (continues the B6/B7 fold-peels-into-chase arc; peellint green). Variants are counted UNGATED (bare prims are type-table singletons, so a bare variant node can BE the source's chased bottom): the >=2 guard stays equivalent to harec's nassign>=2 -> NULL (ref/harec/src/types.c:734-738, tagged_select_subtype P2/P3). >=2 chain hits hard-error with twin texts (prefix convention, shared tail "source alias chain reaches >=2 variants — ambiguous without nominal layout (#95)") — drew's ambiguity proviso extended to the chained set; was a SILENT member-0 tag. Pass-2 bare-source fallback unchanged. Chased type EQUALITY only — no type_is_assignable scalar import, no int widening (ken's binding scalar warning). Pin table (new suite test/wcc/944_variant_chain_b95_run.c, 45 checks, Makefile-wired): GRADUATIONS exit 1->0 both stages: chain_1lvl_i (kb5_v2s1i HEADLINE, byte-id held), chain_2lvl_i, chain_deep_src, chain_deep_var (byte-id held), chain_call_bound81 (kb5_v2s1), chain_call2_bound81 (kb4_v2_struct2, #95's original) — the two CALL-src rows waive byte-id, pre-existing #81 zero-fill asm noise (NO at base too). NEW LOUD: chain_amb_loud (kb95_amb) — silent tag 0 -> hard-error both stages. MUST-NOT-MOVE held: chain_amb_srcA/B (pass-1 precedence), nom_str/nom_err (#218 nominal regression pin), exact_ctl (kb5_v2sE2), bare_ctl/bare_2lvl/bare_ambig/bare_ambig2 (pass-2 controls), callret_bound277 (kb5_v2sE #277 cells unchanged, dual-cell pin). Invariants: ken's 163-row dissolution matrix rerun — exactly 3 movers, all family graduations (v2s1i/v2s1/v2_struct2 1->0), zero non-family movers, detectors unmoved. Five mains cs-vs-ww byte-id OK (ww/w6c/w6a/w6l/wwdump). make all 0; sizelint 0; peellint 0; all 944 suites + 808 green. w6c_ww/wwdump_ww main.combined.ww regen'd (cgenutil.ww embeds).
This commit is contained in:
@@ -2883,6 +2883,42 @@ fn flatvariantidxt(tagged: *tinfo, want: *tinfo) i32 = {
|
||||
p = p.tnext;
|
||||
idx += 1;
|
||||
};
|
||||
// Pass 1b (#95): NAMED source, no exact variant — chain membership.
|
||||
// An alias IS-A every type on its NAMED chain (ali2 is-a ali is-a
|
||||
// base), so declaring the variant as `ali` admits any source whose
|
||||
// chain shares a node with ali's. Two linear NAMED chains intersect
|
||||
// iff they share their chased bottom node (.ai/ken-95-oracle.md §1),
|
||||
// so membership reduces to pointer identity of the chased ends —
|
||||
// tichase is the blessed chase, no raw hops. Variants are counted
|
||||
// UNGATED (bare prims are type-table singletons, so a bare variant
|
||||
// node can BE the source's bottom): that keeps the guard ≡ harec's
|
||||
// nassign>=2 → NULL (ref/harec/src/types.c:734-738; the P1-exact
|
||||
// short-circuit is pass 1 above). >=2 chain hits cannot be
|
||||
// disambiguated once the nominal-lossy model collapses the chain —
|
||||
// hard-error (drew's ambiguity proviso extended to the chained
|
||||
// set). cs twin cg_tag_for_variant fused in this commit.
|
||||
if (want.kind == tykind.TY_NAMED) {
|
||||
let sb: *tinfo = tichase(want);
|
||||
if (sb == nil) { return -1; };
|
||||
let q: *tparam = ti.params;
|
||||
let qi: i32 = 0;
|
||||
let found: i32 = -1;
|
||||
let n: i32 = 0;
|
||||
for (q != nil) {
|
||||
if (q.type_ != nil && tichase(q.type_) == sb) {
|
||||
if (found < 0) { found = qi; };
|
||||
n += 1;
|
||||
};
|
||||
q = q.tnext;
|
||||
qi += 1;
|
||||
};
|
||||
if (n >= 2) {
|
||||
let msg: str = "flatvariantidxt: source alias chain reaches >=2 variants — ambiguous without nominal layout (#95)\n";
|
||||
os.write(2, msg.ptr, msg.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
return found;
|
||||
};
|
||||
// Pass 2 (#15): no exact variant matched — structurally match a BARE
|
||||
// source against a NAMED-alias variant (bare *vtable into the
|
||||
// `stream` (= *vtable) variant of `(file | stream)`). The bare side
|
||||
|
||||
Reference in New Issue
Block a user