docs(fork-c/S0): setup contract — byte-baseline + commit-discipline, E6b disposition + two-corpus partition, A–E6 reuse/delete ledger

S0 of the ratified Fork C plan (zero-legacy name-resolution redesign, S0→S6).
Pure setup/documentation: NO production code change, NO behavior change.
Single-author output byte-identical to wt-stdlib-base by construction.

Deliverables under docs/fork-c/ (docs/, not current/, because current/ is
gitignored and the contract must be committed):

S0.1 — byte-baseline + commit-discipline: the committed examples/expected/*
snapshots are the single-author byte-identity reference; the zero-diff repro is
`zig build && zig build test && bash tests/run_examples.sh`. Resolver-target set
explicitly excluded + listed. Commit-classification rule: mirror | consumer-cutover | deletion.

S0.2 — E6b disposition + two-corpus partition: transitional E6b src NOT merged
(grep-clean: no resolveRegistrationSigTypeInSource / sig_registration_mode /
e6br_gate.test.zig on baseline). Harvested 0811–0829 trees + goldens (never the
src), empirically partitioned by running each through the base compiler vs the
E6b target:
  - baseline-green (mirror-equivalence): 0795–0798 (merged) + 0823, 0828 — given
    examples/expected/ markers, locked into the S0 baseline.
  - resolver-target (known-wrong old behavior): 0811–0822, 0824–0827, 0829 + the
    re-filed E6BR-5 nested-pattern regression — a listed xfail harness under
    tests/resolver-target/ (manifest + TARGET goldens, NO active marker), flips
    active+green at S3.9. 0811/0829 noted as old-selector-wrong on the E6b-unmerged
    base; E6BR-5 subsumed by the whole-AST resolver, NOT an E6b attempt-6.

S0.3 — A–E6 reuse/delete ledger: every load-bearing A–E6 artifact mapped REUSED
(Fork C home) or DELETED/TRANSITIONAL (S3/S6 phase); E6c/d/e dropped, F/H/I/K
absorbed/superseded.

Gate over the baseline-green corpus: zig build + zig build test (LSP corpus sweep
574 files, no crash) + bash tests/run_examples.sh (540 passed, 0 failed) all exit 0.
This commit is contained in:
agra
2026-06-09 10:29:23 +03:00
parent 1f755284d9
commit 1ce3a4e9e0
114 changed files with 1584 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
// E6b — per-decl nominal identity for ERROR-SET decls. A bare ERROR-SET reference
// is non-transitive AND ambiguity-checked at every site, exactly like the struct
// leaf (0755) and the enum/union leaves (0795/0797). `main` flat-imports two
// modules that each author a same-name `IoErr` error set and authors none itself,
// so EACH of the following bare ERROR-SET forms is a genuine collision the source
// cannot disambiguate — and each must emit the LOUD "type 'IoErr' is ambiguous"
// diagnostic and poison the result, NEVER silently pick a global `findByName`
// last-wins author:
//
// - reflection / type-arg slot `size_of(IoErr)`
// - typed error-value annotation `e : IoErr = error.Disk`
// - type-as-value `t : Type = IoErr`
// - type-category match arm `case IoErr:`
// - `!Named` failable channel `-> !IoErr` (E6b audited use surface)
//
// Fail-before (pre-E6b): the stateless `type_bridge.resolveInlineErrorSet`
// `findByName` short-circuit interned ONE global last-wins `IoErr`, so every bare
// form silently resolved to it; the `!IoErr` channel resolved through
// `resolveErrorType -> resolveTypeName` straight to that global slot. The program
// exited 0.
#import "modules/std.sx";
#import "0811-modules-same-name-error-set-ambiguous/a.sx";
#import "0811-modules-same-name-error-set-ambiguous/b.sx";
describe :: ($T: Type) -> s32 {
r := if T == {
case IoErr: 1;
else: 0;
}
r
}
fail_io :: () -> !IoErr {
raise error.Disk;
}
main :: () -> s32 {
sz := size_of(IoErr);
e : IoErr = error.Disk;
t : Type = IoErr;
k := describe(s64);
0
}

View File

@@ -0,0 +1,4 @@
// One of two flat-imported authors of a same-name `IoErr` error set. With both
// modules flat-visible from a file that authors none itself, every bare reference
// to the name is genuinely ambiguous.
IoErr :: error { Disk, Net }

View File

@@ -0,0 +1,4 @@
// The second flat-imported author of a same-name `IoErr` error set. A separate
// nominal identity from a.sx's `IoErr`, so each bare reference is a real collision
// the importing source cannot disambiguate.
IoErr :: error { Disk, Net }

View File

@@ -0,0 +1,28 @@
// E6b — own-wins-over-flat for ERROR-SET per-decl nominal identity. `main`
// flat-imports `dep.sx` (which authors `IoErr { Net }`) AND authors its OWN
// `IoErr { Disk }`. A bare `IoErr` reference in `main` resolves to `main`'s OWN
// author, not the flat-imported one (the querying source's author wins outright —
// no ambiguity), so `e : IoErr = error.Disk` binds `main`'s set (whose `Disk` tag
// dep's `IoErr` lacks) while `dep_err()` returns dep's DISTINCT `IoErr`.
//
// Fail-before (pre-E6b): the stateless `type_bridge.resolveInlineErrorSet`
// `findByName` short-circuit interned ONE global last-wins `IoErr`, so `main`'s
// `IoErr` and dep's `IoErr` collapsed to a single nominal. Whichever author won
// the global slot, the OTHER module's tag is not in it — so exactly one of
// `error.Disk` (main) / `error.Net` (dep, in `dep_err`'s body) fails its
// membership check and the program exits 1.
//
// Pass-after: distinct nominal TypeIds — `error.Disk` validates against main's
// `{ Disk }` and `error.Net` against dep's `{ Net }`, both pass, exit 0.
#import "modules/std.sx";
#import "0812-modules-same-name-error-set-own-wins/dep.sx";
IoErr :: error { Disk }
main :: () -> s32 {
e : IoErr = error.Disk;
d := dep_err();
print("own={} dep={}\n", e, d);
0
}

View File

@@ -0,0 +1,10 @@
// A flat-imported module authors its OWN `IoErr { Net }`. The importing file
// (`main`) ALSO authors an `IoErr` — its own author must win there (own-wins),
// while this module's `IoErr` stays a DISTINCT nominal type used by `dep_err`.
// The tag sets are disjoint, so a cross-binding to the wrong `IoErr` is a hard
// compile error (`Net` is not in main's `{ Disk }`, and vice-versa).
IoErr :: error { Net }
dep_err :: () -> IoErr {
return error.Net;
}

View File

@@ -0,0 +1,30 @@
// E6b — own-wins for an ERROR-SET name in a CLOSURE-LITERAL return annotation
// (`closure(() -> !IoErr { … })`). `main` flat-imports `dep.sx` (which authors
// `IoErr { Net }`) AND authors its OWN `IoErr { Disk }`. The closure literal's
// `-> !IoErr` channel must resolve to `main`'s OWN author (own-wins), so the
// `raise error.Disk` inside the closure body validates against main's `{ Disk }`;
// meanwhile `dep_err` keeps dep's DISTINCT `IoErr { Net }`.
//
// Fail-before (attempt-1): `lowerLambda` resolved the explicit `lam.return_type`
// through the STATELESS `type_bridge.resolveAstType`, so the closure's `!IoErr`
// channel bound the global last-wins author (dep's `{ Net }`); `error.Disk` was
// then "not in error set 'IoErr'" and the program exited 1.
//
// Pass-after: the lambda return annotation routes through the source-aware
// `resolveTypeWithBindings` (same path as the regular function-return channel),
// main's own `IoErr` wins, `error.Disk` validates, exit 0.
#import "modules/std.sx";
#import "0813-modules-same-name-error-set-lambda-own-wins/dep.sx";
IoErr :: error { Disk }
main :: () -> s32 {
fail_own := closure(() -> !IoErr { raise error.Disk; });
fail_own() catch e {
if e == error.Disk { print("own=Disk\n"); }
};
d := dep_err();
print("dep={}\n", d);
return 0;
}

View File

@@ -0,0 +1,11 @@
// A flat-imported module authors its OWN `IoErr { Net }`. The importing file
// (`main`) ALSO authors an `IoErr` AND uses it as a closure-literal return
// annotation (`-> !IoErr`); main's author must win THERE too (own-wins),
// while this module's `IoErr` stays a DISTINCT nominal used by `dep_err`.
// The tag sets are disjoint, so binding the wrong `IoErr` is a hard compile
// error (`Net` is not in main's `{ Disk }`, and vice-versa).
IoErr :: error { Net }
dep_err :: () -> IoErr {
return error.Net;
}

View File

@@ -0,0 +1,27 @@
// E6b — ambiguity guard for an ERROR-SET name in a CLOSURE-LITERAL return
// annotation (`closure(() -> !IoErr { … })`). `main` flat-imports two modules
// that each author a same-name `IoErr` and authors none itself, so the closure
// literal's `-> !IoErr` channel is a genuine collision the source cannot
// disambiguate. It must emit the LOUD "type 'IoErr' is ambiguous" diagnostic and
// poison the channel — NEVER silently pick a global `findByName` last-wins author.
//
// NOTE on fail-before/pass-after: unlike the OWN-WINS sibling (0813), this
// AMBIGUITY case does NOT fail-before on attempt-1's binary. The pre-lowering
// closure-shape pass (`convergeClosureShapeSets` → `recordClosureShape`) resolves
// every closure literal's return annotation through the source-aware
// `resolveType` (`resolveTypeWithBindings`), which attempt-1 already routed
// error-set authors through — so the ambiguity is detected there and reported
// regardless of `lowerLambda`. (For a `-> !Named` set that pass bails early after
// resolving, so the OWN-WINS membership in 0813 still flowed through the stateless
// `lowerLambda` path that attempt-2 fixes.) This example is the standing GUARD
// that the lambda `-> !Named` ambiguity stays reported across both source-aware
// sites; 0813 is the one that exercises attempt-2's `lowerLambda` channel fix.
#import "modules/std.sx";
#import "0814-modules-same-name-error-set-lambda-ambiguous/a.sx";
#import "0814-modules-same-name-error-set-lambda-ambiguous/b.sx";
main :: () -> s32 {
fail_io := closure(() -> !IoErr { return; });
return 0;
}

View File

@@ -0,0 +1,4 @@
// One of two flat-imported authors of a same-name `IoErr` error set. With both
// modules flat-visible from a file that authors none itself, the `-> !IoErr`
// closure-literal channel is genuinely ambiguous.
IoErr :: error { Disk, Net }

View File

@@ -0,0 +1,4 @@
// The second flat-imported author of a same-name `IoErr` error set. A separate
// nominal identity from a.sx's `IoErr`, so the `-> !IoErr` closure-literal channel
// is a real collision the importing source cannot disambiguate.
IoErr :: error { Disk, Net }

View File

@@ -0,0 +1,35 @@
// E6b-R — route-all: the NEW use surfaces a same-name type reaches now funnel
// through the source-aware engine, so an ambiguous bare name poisons LOUDLY at
// each of them instead of silently picking a global `findByName` last-wins author.
// `main` flat-imports two same-name `Box` struct authors and authors none itself,
// so every bare `Box` below is a genuine collision. `Box` is the kind-agnostic
// canary (the bare-leaf forms — annotations / size_of / match / `!Named` — are
// already locked per kind by 0755/0795/0797/0811); these cells exercise the
// surfaces E6b-R added:
//
// - wrapper-alias element `BoxPtr :: *Box` (engine wrapper aliasing)
// - union body-builder child `WrapU :: union { b: Box }` (C1, registerUnionDecl)
// - enum body-builder child `WrapE :: enum { V: Box }` (C1, registerEnumDecl)
// - tuple-literal element `size_of((Box, s32))` (O1/K5)
// - inline-anonymous body child `x : union { b: Box }` (inline-anon engine arm)
//
// Fail-before (pre-E6b-R): each of these resolved `Box` through the stateless
// `type_bridge.resolveAstType` global last-wins, silently binding one arbitrary
// author with NO diagnostic. Pass-after: every surface emits the LOUD
// "type 'Box' is ambiguous" and the build exits 1.
#import "modules/std.sx";
#import "0815-route-all-new-surfaces-ambiguous/a.sx";
#import "0815-route-all-new-surfaces-ambiguous/b.sx";
BoxPtr :: *Box;
WrapU :: union { b: Box; n: s32; }
WrapE :: enum { V: Box; }
main :: () -> s32 {
sz := size_of((Box, s32));
x : union { b: Box; n: s32 } = ---;
0
}

View File

@@ -0,0 +1,6 @@
// One of two flat-imported authors of a same-name `Box` struct. With both modules
// flat-visible from a file that authors none itself, every bare reference to the
// name is genuinely ambiguous — at EVERY use surface, including the ones E6b-R
// newly routed through the source-aware engine (wrapper aliases, tuple-literal
// elements, enum/union body-builder child types, inline-anonymous types).
Box :: struct { x: s32; }

View File

@@ -0,0 +1,4 @@
// The second flat-imported author of a same-name `Box` struct. A separate nominal
// identity from a.sx's `Box`, so each bare reference is a real collision the
// importing source cannot disambiguate.
Box :: struct { x: s32; }

View File

@@ -0,0 +1,29 @@
// E6b-R — own-wins-over-flat at the NEW use surfaces route-all funnels through the
// source-aware engine. `main` flat-imports `dep.sx` (which authors `Box { a }`) AND
// authors its OWN `Box { m }`; the field sets are DISJOINT, so the observable is
// field access: `.m` typechecks only against main's `Box`, `.a` only against dep's.
//
// `WrapU` is authored only by `main`, so its union field type `Box` resolves at
// registration (`registerUnionDecl` → the source-aware body builder, E6b-R C1) to
// MAIN's `Box`. Accessing `w.b.m` therefore typechecks, while `dep_box` uses dep's
// DISTINCT `Box { a }`.
//
// Fail-before (pre-E6b-R): `registerUnionDecl` built the union body through the
// stateless `type_bridge.buildUnionInfo`, whose `findByName` short-circuit bound
// the global last-wins `Box`. If dep's `Box { a }` won the slot, `WrapU.b` was
// dep's `Box` and `w.b.m` was a hard "field not found" — silently wrong nominal.
// Pass-after: the union field is main's own `Box`, `w.b.m` resolves, exit 0.
#import "modules/std.sx";
#import "0816-route-all-new-surfaces-own-wins/dep.sx";
Box :: struct { m: s32; }
WrapU :: union { b: Box; n: s32; }
main :: () -> s32 {
w : WrapU = ---;
w.b.m = 5;
print("own={} dep={}\n", w.b.m, dep_box());
0
}

View File

@@ -0,0 +1,11 @@
// A flat-imported module authors its OWN `Box { a }`. The importing file (`main`)
// ALSO authors a `Box { m }` — its own author must win there (own-wins), while this
// module's `Box` stays a DISTINCT nominal type used by `dep_box`. The field sets
// are disjoint, so a cross-binding to the wrong `Box` is a hard compile error.
Box :: struct { a: s32; }
dep_box :: () -> s32 {
b : Box = ---;
b.a = 9;
return b.a;
}

View File

@@ -0,0 +1,20 @@
// E6BR-1 — a plain qualified `ns.Type` type ANNOTATION resolves to the namespace
// target module's OWN member type. `a.Box` parses as a single dotted `type_expr`,
// so it reaches the bare nominal-leaf path; before E6BR-1 that path had no
// dot-qualified split and fabricated an empty-struct stub literally named
// "a.Box", so `x.a` failed with `field 'a' not found on type 'a.Box'` — even with
// this SINGLE namespace import and NO same-name flat author.
//
// Pass-after: `resolveNominalLeaf` dot-splits the name and routes it through the
// namespace-author selector (`qualifiedNamedTypeTid`), binding `a`'s real
// `Box { a }`, so `x.a` resolves, exit 0.
#import "modules/std.sx";
a :: #import "0817-modules-qualified-annotation-single-import-resolve/dep.sx";
main :: () -> s32 {
x : a.Box = ---;
x.a = 4;
print("x.a={}\n", x.a);
0
}

View File

@@ -0,0 +1,3 @@
// The namespace target module authors its OWN `Box { a }`. A qualified `a.Box`
// type annotation in the importer must bind THIS type, not a stub named "a.Box".
Box :: struct { a: s32; }

View File

@@ -0,0 +1,21 @@
// G1 (struct) — a qualified `a.Box` annotation selects the NAMESPACE target's OWN
// `Box`, distinct from `main`'s same-name bare author. `main` authors its OWN
// `Box { m }` AND namespace-imports `a` (which authors `Box { a }`). A bare `Box`
// binds main's own author (own-wins); the qualified `a.Box` binds `a`'s DISTINCT
// nominal even though main has a same-name bare author. The field sets are
// disjoint, so a cross-binding (`q.m` / `own.a`) is a hard compile error — the
// example compiling and running proves the two `Box`es are distinct nominals.
#import "modules/std.sx";
a :: #import "0818-modules-qualified-annotation-own-wins/dep.sx";
Box :: struct { m: s32; }
main :: () -> s32 {
own : Box = ---;
own.m = 5;
q : a.Box = ---;
q.a = 9;
print("own.m={} q.a={}\n", own.m, q.a);
0
}

View File

@@ -0,0 +1,3 @@
// Namespace target authoring its OWN `Box { a }`. The importer (`main`) also
// authors a same-name bare `Box { m }`; the qualified `a.Box` must bind THIS one.
Box :: struct { a: s32; }

View File

@@ -0,0 +1,19 @@
// G1 (non-struct kind = error-set) — a qualified `a.IoErr` annotation selects the
// namespace target's OWN error-set per-decl nominal, distinct from `main`'s
// same-name `IoErr`. `main` authors `IoErr { Disk }` and namespace-imports `a`
// (`IoErr { Net }`). The bare `IoErr` binds main's own (so `error.Disk` is valid);
// the qualified `a.IoErr` binds `a`'s (so `error.Net` is valid). The tag sets are
// disjoint, so a cross-binding (`a.IoErr = error.Disk`) is a hard membership error
// — distinct error-set nominals reached through the qualified annotation surface.
#import "modules/std.sx";
a :: #import "0819-modules-qualified-annotation-error-set-own-wins/dep.sx";
IoErr :: error { Disk }
main :: () -> s32 {
e : IoErr = error.Disk;
q : a.IoErr = error.Net;
print("own={} q={}\n", e, q);
0
}

View File

@@ -0,0 +1,4 @@
// Namespace target authoring its OWN error-set `IoErr { Net }`. The importer
// (`main`) also authors a same-name `IoErr { Disk }`; the qualified `a.IoErr` must
// bind THIS one (whose `Net` tag main's `IoErr` lacks).
IoErr :: error { Net }

View File

@@ -0,0 +1,37 @@
// E6BR-2 / G8 (own-wins) — a protocol method-signature CONCRETE named return type
// resolves SOURCE-AWARE, pinned to the protocol's defining module. `main`
// flat-imports `dep.sx` (`Box { a }`) AND authors its OWN `Box { m }`; the
// protocol `Provider` returns `Box` and the impl builds main's `Box`. Dispatching
// `p.get()` must type the result as MAIN's `Box`, so `b.m` resolves.
//
// Fail-before (pre-E6BR-2): the method signature went through the no-author
// `type_bridge.resolveTemplateSignatureType` wrapper (global last-wins), so the
// return typed as dep's `Box { a }` and `b.m` was `field 'm' not found on type
// 'Box'`. Pass-after: source-aware → main's `Box`, exit 0.
#import "modules/std.sx";
#import "0820-protocols-same-name-method-own-wins/dep.sx";
Box :: struct { m: s32; }
Provider :: protocol {
get :: () -> Box;
}
Holder :: struct { val: s32 = 7; }
impl Provider for Holder {
get :: (self: *Holder) -> Box {
b : Box = ---;
b.m = self.val;
b
}
}
main :: () -> s32 {
h : Holder = .{};
p : Provider = xx @h;
b := p.get();
print("m={} dep={}\n", b.m, dep_box());
0
}

View File

@@ -0,0 +1,10 @@
// A flat-imported module authors its OWN `Box { a }`, a DISTINCT nominal from
// main's same-name `Box { m }`. The protocol method-signature return must NOT bind
// this one — the disjoint field sets make a wrong binding a hard compile error.
Box :: struct { a: s32; }
dep_box :: () -> s32 {
b : Box = ---;
b.a = 9;
return b.a;
}

View File

@@ -0,0 +1,18 @@
// G8 (ambiguous half) — because a protocol method-signature concrete return type
// is now resolved SOURCE-AWARE, a genuinely ambiguous same-name type poisons
// LOUDLY at the protocol declaration instead of silently picking a global
// `findByName` last-wins author. `main` flat-imports two `Box` authors and
// declares none itself, so the `Provider.get` return `Box` is an unresolvable
// collision and the build exits 1.
#import "modules/std.sx";
#import "0821-protocols-same-name-method-ambiguous/a.sx";
#import "0821-protocols-same-name-method-ambiguous/b.sx";
Provider :: protocol {
get :: () -> Box;
}
main :: () -> s32 {
0
}

View File

@@ -0,0 +1,3 @@
// One of two flat-imported same-name `Box` authors — the bare `Box` in the
// protocol return is a genuine collision the source cannot disambiguate.
Box :: struct { a: s32; }

View File

@@ -0,0 +1,3 @@
// The second flat-imported same-name `Box` author. Two distinct flat authors and
// no own author → the protocol return `Box` is ambiguous.
Box :: struct { b: s32; }

View File

@@ -0,0 +1,39 @@
// G3 — own-wins HALVES for the route-all surfaces 0815 covered only on the
// ambiguous half. `main` authors its OWN `Box { m }` and flat-imports `dep.sx`
// (`Box { a }`); each surface below must bind main's OWN `Box`, observed by a
// `.m` access (disjoint field sets → a wrong-author binding is a hard compile
// error). Complements 0816 (which covered only the union body-builder child):
// - pointer wrapper-alias element `BoxPtr :: *Box`
// - tuple element `(Box, s32)`
// - enum body-builder child `WrapE :: enum { V: Box }`
// - inline-anonymous union child `x : union { b: Box }`
#import "modules/std.sx";
#import "0822-route-all-own-wins-surfaces/dep.sx";
Box :: struct { m: s32; }
BoxPtr :: *Box;
WrapE :: enum { V: Box; }
main :: () -> s32 {
own : Box = ---;
own.m = 10;
// *Named wrapper-alias element own-wins
bp : BoxPtr = @own;
// tuple element own-wins
t : (Box, s32) = ---;
t.0.m = 12;
// enum body-builder child own-wins (payload must be main's `Box`)
we : WrapE = .V(own);
ev := we.V.m;
// inline-anonymous union child own-wins
x : union { b: Box; n: s32 } = ---;
x.b.m = 13;
print("bp={} t={} ev={} x={} dep={}\n", bp.m, t.0.m, ev, x.b.m, dep_box());
0
}

View File

@@ -0,0 +1,10 @@
// A flat-imported module authoring its OWN `Box { a }`, a DISTINCT nominal from
// main's `Box { m }`. The four route-all surfaces in `main` must each bind main's
// own `Box`; the disjoint field sets make a wrong binding a hard compile error.
Box :: struct { a: s32; }
dep_box :: () -> s32 {
b : Box = ---;
b.a = 99;
return b.a;
}

View File

@@ -0,0 +1,32 @@
// G4 — own-wins halves for the §D row-2 SUB-FORM wrappers (`?Named`, `[]Named`,
// `[N]Named`). Each wraps a named element type whose resolution recurses through
// the SAME source-aware `resolveCompound` element path that `*Named` uses (0822),
// so they share one routing mechanism rather than a per-form path. `main` authors
// its OWN `Box { m }` and flat-imports `dep.sx` (`Box { a }`); each wrapped
// element must bind main's own `Box`, observed by a `.m` access (disjoint field
// sets → a wrong-author binding is a hard compile error).
#import "modules/std.sx";
#import "0823-route-all-own-wins-subform-wrappers/dep.sx";
Box :: struct { m: s32; }
main :: () -> s32 {
seed : Box = ---;
seed.m = 1;
// ?Named element own-wins
opt : ?Box = seed;
o := opt!;
// [N]Named element own-wins
arr : [2]Box = ---;
arr[0].m = 2;
arr[1].m = 3;
// []Named element own-wins
sl : []Box = arr[0..2];
print("opt={} arr={} sl={} dep={}\n", o.m, arr[0].m, sl[1].m, dep_box());
0
}

View File

@@ -0,0 +1,10 @@
// A flat-imported module authoring its OWN `Box { a }`, a DISTINCT nominal from
// main's `Box { m }`. The `?Box` / `[N]Box` / `[]Box` element wrappers in `main`
// must each bind main's own `Box`; disjoint field sets make a wrong binding fail.
Box :: struct { a: s32; }
dep_box :: () -> s32 {
b : Box = ---;
b.a = 99;
return b.a;
}

View File

@@ -0,0 +1,78 @@
// E6BR-4 (own-wins) — a protocol method-signature names a same-name `Box` under
// every WRAPPER / COMPOUND form, and each must resolve SOURCE-AWARE (pinned to the
// protocol's defining module = main), selecting main's OWN `Box { m }` rather than
// the global last-wins `Box { a }` from the flat-imported `dep.sx`.
//
// The reconciled choke-point (resolveRegistrationSigTypeInSource → the recursive
// source-aware engine) recurses every structural shape and resolves the leaf
// author own-wins. The E6BR-4 RED CELL is the WRAPPED RETURN `() -> *Box`: pre-fix
// the wrapped sig fell to the no-author `type_bridge.resolveTemplateSignatureType`
// (global last-wins) and typed the result as `dep`'s `Box { a }`, so `bp.m` was
// `field 'm' not found on type 'Box'`. Discriminating returns: `*Box`, `?Box`,
// `(Box,Box)`, `[2]Box` (each observed by a `.m` access). Routing-only params:
// `*Box`, `?Box`, `[]Box`, `[2]Box`, `(Box,Box)`, nested `*?[]Box` — all resolved
// through the same `resolveCompound` recursion at protocol-decl registration.
#import "modules/std.sx";
#import "0824-protocols-same-name-method-wrapped-own-wins/dep.sx";
Box :: struct { m: s32; }
Holder :: struct { b: Box = ---; }
Provider :: protocol {
// discriminating wrapped/compound RETURNS
getp :: () -> *Box;
geto :: () -> ?Box;
gett :: () -> (Box, Box);
geta :: () -> [2]Box;
// routing-only wrapped/compound PARAMS
sump :: (p: *Box) -> s32;
sumo :: (o: ?Box) -> s32;
sums :: (s: []Box) -> s32;
suma :: (a: [2]Box) -> s32;
sumt :: (t: (Box, Box)) -> s32;
sumn :: (n: *?[]Box) -> s32;
}
impl Provider for Holder {
getp :: (self: *Holder) -> *Box { @self.b }
geto :: (self: *Holder) -> ?Box { self.b }
gett :: (self: *Holder) -> (Box, Box) { (self.b, self.b) }
geta :: (self: *Holder) -> [2]Box { r : [2]Box = ---; r[0] = self.b; r[1] = self.b; r }
sump :: (self: *Holder, p: *Box) -> s32 { p.m }
sumo :: (self: *Holder, o: ?Box) -> s32 { o!.m }
sums :: (self: *Holder, s: []Box) -> s32 { s[0].m }
suma :: (self: *Holder, a: [2]Box) -> s32 { a[0].m }
sumt :: (self: *Holder, t: (Box, Box)) -> s32 { t.0.m }
sumn :: (self: *Holder, n: *?[]Box) -> s32 { if n == null { 0 } else { 6 } }
}
main :: () -> s32 {
h : Holder = ---;
h.b.m = 7;
p : Provider = xx @h;
// discriminating returns — `.m` only resolves if each binds main's `Box`
bp := p.getp();
bo := p.geto();
bt := p.gett();
ba := p.geta();
// routing-only params, constructed in main and passed through the protocol
one : Box = ---; one.m = 1;
arr : [2]Box = ---; arr[0].m = 2; arr[1].m = 3;
sl : []Box = arr[0..2];
osl : ?[]Box = sl;
tup : (Box, Box) = (one, one);
sp := p.sump(@one);
so := p.sumo(one);
ss := p.sums(sl);
sa := p.suma(arr);
st := p.sumt(tup);
sn := p.sumn(@osl);
print("p={} o={} t={} a={} | sp={} so={} ss={} sa={} st={} sn={} dep={}\n",
bp.m, bo!.m, bt.0.m, ba[0].m, sp, so, ss, sa, st, sn, dep_box());
0
}

View File

@@ -0,0 +1,11 @@
// A flat-imported module authors its OWN `Box { a }`, a DISTINCT nominal from
// main's same-name `Box { m }`. The protocol method signatures below name `Box`
// under every wrapper/compound form; a wrong (last-wins) author binds this `Box`,
// whose disjoint field set makes a `.m` access a hard compile error.
Box :: struct { a: s32; }
dep_box :: () -> s32 {
b : Box = ---;
b.a = 9;
return b.a;
}

View File

@@ -0,0 +1,23 @@
// E6BR-4 (ambiguous) — because a protocol method-signature WRAPPED return type is
// now resolved SOURCE-AWARE (the reconciled choke-point recurses `*Box` and
// resolves its leaf via `resolveNominalLeaf`), a genuinely ambiguous same-name
// element poisons LOUDLY at the protocol declaration instead of silently picking a
// global `findByName` last-wins author. `main` flat-imports two `Box` authors and
// declares none itself, so the `Provider.getp` return `*Box` is an unresolvable
// collision and the build exits 1.
//
// Fail-before (pre-E6BR-4): the wrapped `*Box` fell to the no-author
// `type_bridge.resolveTemplateSignatureType` wrapper (global last-wins, no
// diagnostic), so the build did NOT report the collision.
#import "modules/std.sx";
#import "0825-protocols-same-name-method-wrapped-ambiguous/a.sx";
#import "0825-protocols-same-name-method-wrapped-ambiguous/b.sx";
Provider :: protocol {
getp :: () -> *Box;
}
main :: () -> s32 {
0
}

View File

@@ -0,0 +1,9 @@
// One of two flat-imported `Box` authors. With no own author in main, the
// protocol method-signature `() -> *Box` is a genuine collision.
Box :: struct { a: s32; }
a_box :: () -> s32 {
b : Box = ---;
b.a = 1;
return b.a;
}

View File

@@ -0,0 +1,8 @@
// The second flat-imported `Box` author — a DISTINCT nominal from a.sx's `Box`.
Box :: struct { b: s32; }
b_box :: () -> s32 {
x : Box = ---;
x.b = 2;
return x.b;
}

View File

@@ -0,0 +1,32 @@
// E6BR-4 (param-impl SOURCE, own-wins) — a parameterised-impl SOURCE type under a
// wrapper (`impl Into(Marker) for *Box`) registers SOURCE-AWARE, pinned to the
// impl's defining module (main), and the `xx` lookup at the use site mangles to the
// SAME author, so the conversion is found and runs. `main` authors its OWN
// `Box { m }` and flat-imports `dep.sx` (`Box { a }`); the `*Box` source binds
// main's `Box`, so `convert`'s `self.m` resolves and `xx @b` selects this impl.
//
// This locks the route-all registration path for the param-impl-source surface:
// the source `*Box` flows through `resolveRegistrationSigTypeInSource` →
// `resolveCompound` → `resolveNominalLeaf` (own-wins), never the no-author leaf.
// The param_impl_map key is name-based (`Into\0Marker\0*Box`), so registration and
// `tryUserConversion` agree by construction.
#import "modules/std.sx";
#import "0826-protocols-param-impl-source-wrapped-own-wins/dep.sx";
Box :: struct { m: s32; }
Marker :: struct { v: s32; }
impl Into(Marker) for *Box {
convert :: (self: *Box) -> Marker {
.{ v = self.m }
}
}
main :: () -> s32 {
b : Box = ---;
b.m = 7;
mk : Marker = xx @b;
print("v={} dep={}\n", mk.v, dep_box());
0
}

View File

@@ -0,0 +1,11 @@
// A flat-imported module authors its OWN `Box { a }`, a DISTINCT nominal from
// main's same-name `Box { m }`. The param-impl SOURCE `*Box` must register against
// main's `Box`, and the `xx` lookup at the use site must mangle to the SAME author,
// so the conversion is found and `self.m` resolves.
Box :: struct { a: s32; }
dep_box :: () -> s32 {
b : Box = ---;
b.a = 9;
return b.a;
}

View File

@@ -0,0 +1,27 @@
// E6BR-4 (param-impl SOURCE, ambiguous) — because a parameterised-impl wrapped
// SOURCE type is now registered SOURCE-AWARE (the source `*Box` flows through
// `resolveRegistrationSigTypeInSource` → `resolveCompound` → `resolveNominalLeaf`),
// a genuinely ambiguous same-name element poisons LOUDLY at registration instead of
// silently selecting a global `findByName` last-wins author. `main` flat-imports two
// `Box` authors and declares none itself, so `impl Into(Marker) for *Box` cannot
// pick a `Box` and the build exits 1.
//
// Fail-before (pre-E6BR-4): the source `*Box` fell to the no-author
// `type_bridge.resolveTemplateSignatureType` wrapper (global last-wins, no
// diagnostic), so the collision was registered silently.
#import "modules/std.sx";
#import "0827-protocols-param-impl-source-wrapped-ambiguous/a.sx";
#import "0827-protocols-param-impl-source-wrapped-ambiguous/b.sx";
Marker :: struct { v: s32; }
impl Into(Marker) for *Box {
convert :: (self: *Box) -> Marker {
.{ v = 0 }
}
}
main :: () -> s32 {
0
}

View File

@@ -0,0 +1,9 @@
// One of two flat-imported `Box` authors; with no own author the param-impl
// SOURCE `*Box` is a genuine collision.
Box :: struct { a: s32; }
a_box :: () -> s32 {
b : Box = ---;
b.a = 1;
return b.a;
}

View File

@@ -0,0 +1,8 @@
// The second flat-imported `Box` author — a DISTINCT nominal from a.sx's `Box`.
Box :: struct { b: s32; }
b_box :: () -> s32 {
x : Box = ---;
x.b = 2;
return x.b;
}

View File

@@ -0,0 +1,31 @@
// E6BR-4 (param-impl ARG, own-wins) — a parameterised-impl PROTOCOL TYPE-ARG under
// a wrapper (`impl Tagged(*Box) for Holder`) is resolved through the same
// source-aware registration helper (`resolveRegistrationSigTypeInSource` with the
// `.param_impl_arg` purpose), pinned to the impl's defining module (main). The arg
// `*Box` flows through `resolveCompound` → `resolveNominalLeaf` and selects main's
// OWN `Box { m }` rather than the flat-imported `dep.sx` `Box { a }`, so the impl
// registers and `Holder.tag` is callable. (The `param_impl_map` key is name-based,
// so own-wins registration and any later lookup agree by construction; this cell
// locks that the wrapped arg routes through the engine, not the no-author leaf.)
#import "modules/std.sx";
#import "0828-protocols-param-impl-arg-wrapped-own-wins/dep.sx";
Box :: struct { m: s32; }
Holder :: struct { n: s32; }
Tagged :: protocol(T: Type) {
tag :: () -> s32;
}
impl Tagged(*Box) for Holder {
tag :: (self: *Holder) -> s32 {
self.n
}
}
main :: () -> s32 {
h : Holder = .{ n = 7 };
print("tag={} dep={}\n", h.tag(), dep_box());
0
}

View File

@@ -0,0 +1,11 @@
// A flat-imported module authors its OWN `Box { a }`, a DISTINCT nominal from
// main's same-name `Box { m }`. The parameterised-impl protocol type-ARG `*Box`
// registers SOURCE-AWARE against main's `Box` (own-wins), never the global
// last-wins author.
Box :: struct { a: s32; }
dep_box :: () -> s32 {
b : Box = ---;
b.a = 9;
return b.a;
}

View File

@@ -0,0 +1,36 @@
// E6BR-4 (MIXED pack source — the trap cell) — a pack-closure param-impl source
// `Closure(*Box, ..$args) -> $R` mixes a CONCRETE fixed prefix (`*Box`) with pack
// metadata (`..$args`, `$R`). The reconciled choke-point decides template-vs-author
// AT THE LEAF: `*Box` is resolved SOURCE-AWARE through `resolveCompound` while
// `..$args`/`$R` stay pack metadata via `PackResolver` — NOT a top-level
// "contains-unbound → no-author wrapper" router, which would send `*Box` down the
// global last-wins path (the trap both engines flagged). With two flat `Box`
// authors and none own, the concrete `*Box` prefix is a genuine collision and the
// build exits 1 — proving the prefix IS routed source-aware (it caught the
// ambiguity) while the pack parts did not spuriously error.
//
// Fail-before (pre-E6BR-4): the wrapped/pack source fell to the no-author
// `type_bridge.resolveTemplateSignatureType` wrapper (global last-wins, no
// diagnostic), so the `*Box` collision registered silently. Protects the pure-pack
// `Closure(..$args) -> $R` bridge in `library/modules/std/objc_block.sx` (0504 /
// 1302 / 1304 stay byte-identical), whose single author keeps the prefix-free path.
#import "modules/std.sx";
#import "0829-packs-param-impl-mixed-pack-source-ambiguous/a.sx";
#import "0829-packs-param-impl-mixed-pack-source-ambiguous/b.sx";
Block :: struct { tag: s32; }
Sink :: protocol(T: Type) {
convert :: () -> T;
}
impl Sink(Block) for Closure(*Box, ..$args) -> $R {
convert :: (self: Closure(*Box, ..$args) -> $R) -> Block {
.{ tag = 0 }
}
}
main :: () -> s32 {
0
}

View File

@@ -0,0 +1,9 @@
// One of two flat-imported `Box` authors; with no own author the FIXED PREFIX
// `*Box` of the pack-closure source is a genuine collision.
Box :: struct { a: s32; }
a_box :: () -> s32 {
b : Box = ---;
b.a = 1;
return b.a;
}

View File

@@ -0,0 +1,8 @@
// The second flat-imported `Box` author — a DISTINCT nominal from a.sx's `Box`.
Box :: struct { b: s32; }
b_box :: () -> s32 {
x : Box = ---;
x.b = 2;
return x.b;
}

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1 @@
opt=1 arr=2 sl=3 dep=99

View File

@@ -0,0 +1 @@
tag=7 dep=9