107d31cc01400a41e4e036af6b7c60a2e5d0463a
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| fc50a27f3e |
cgen: #95 c3 reviewer-fold — is/as gate exact-only, no widening leak
c1/c2 widened flatvariantidxt (selfhost) with the chain + structural tag-synthesis arms and a >=2 ambiguity os.exit, scoped to the cgen WIDEN consumer. But flatvariantidxt is a choke-point: the wwstage is/as ACCEPTANCE gate (check.ww:4677, the #198 spread fallback) reuses it, so the widening leaked into checker acceptance — vs base |
|||
| 56aac85f6f |
cgen: #95 c2 structural variant fallback — both-stage fused
A nominally-unrelated, structurally-equal NAMED source into a NAMED
variant (kb95_unrel: ta/tb same-layout structs, src ta -> (void|tb))
was LIVE both-wrong-identical byte-id silent: both checkers accept,
both cgens tagged 0. After c1's chain arm finds no shared chain
node, match the variant whose CHASED type type_eq's/typeeq's the
source's chased bottom — chased type EQUALITY only, no
type_is_assignable scalar import, no int widening (ken's binding
scalar warning). Same NAMED-source branch, both stages
(cg_tag_for_variant / flatvariantidxt), forced fuse.
Correctness reference, cite 1 — harec tagged_select_subtype P2+P3
(ref/harec/src/types.c:702-739), verbatim:
if (t->id == subtype->id) {
return t;
}
if (type_is_assignable(ctx, t, subtype)) {
selected = t;
++nassign;
}
...
if (nassign == 1) {
return selected;
}
return NULL;
with type_is_assignable's non-tagged path dealiasing both sides and
accepting composites only via interned pointer equality
(types.c:988-1002), verbatim:
if (type_dealias(ctx, to)->storage != STORAGE_TAGGED) {
to = type_dealias(ctx, to);
from = type_dealias(ctx, from);
}
...
if (to == from && to->storage != STORAGE_VOID) {
return true;
}
Cite 2 — type_hash interns bare composites STRUCTURALLY (banked as
types.c:72-81; verified in the vendored copy at types.c:444 +
struct/union arm :514-525), verbatim:
case STORAGE_UNION:
hash = fnv1a_size(hash, type->struct_union.packed);
for (const struct struct_field *field = type->struct_union.fields;
field; field = field->next) {
if (field->name) {
hash = fnv1a_s(hash, field->name);
}
hash = fnv1a_u32(hash, type_hash(field->type));
hash = fnv1a_size(hash, field->offset);
}
— no decl ident in the hash, so harec's two decls dealias to ONE
interned node and `to == from` holds: acceptance is DEFINITIONAL
under interning, not an arm whose text could be misread. Our store
does not intern; chased type equality is the non-interned rendering
of the same rule.
Honest divergence (the >=2-structural-match hard-error STAYS): under
harec's interning two structurally-identical variants are ONE type —
a union cannot contain it twice — so the ambiguity case is
unrepresentable there; our hard-error (twin texts, shared tail
"source structurally matches >=2 variants — ambiguous without
nominal layout (#95)") is the correct nominal-lossy-model rendering,
not a harec deviation.
Pin table: unrel_struct row added (kb95_unrel graduates ok/1-ok/1 ->
0/0, byte-id held) — suite now 48/48. All c1 rows unmoved.
Invariants: 163-row dissolution matrix at tip — same 3 family
graduations as c1, ZERO new movers; five mains cs-vs-ww byte-id OK;
make all 0; sizelint 0; peellint 0 (no new peel sites — the
structural leg reads only chased ends); all 944 suites + 808 green.
w6c_ww/wwdump_ww main.combined.ww regen'd.
|
|||
| 34c86bd681 |
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). |