test: port 696/697/699 resolver carriers to corpus fixtures
696_modtype_leaf_collision.c -> r696_modtype_leaf_pos (run-exit 26),
r696_modtype_leaf_neg (staged error; w6c 'no field', w6c_ww
asserttyped: dot — the old no-wwstage-checkfile comment is stale)
697_samemod_prefer.c -> r697_samemod_prefer (compile)
699_use_promote_alias.c -> r699_usepromote_{type,fn,def,var}
(run-exit 42 each)
Single-file multi-package form folds the modcollision/samemodprefer/
usepromote data trees into the fixtures; the trees retire with their
carriers. The dir-tree .wwi transport of colliding type decls is owned
by test/byteid/wwi_test.ww. Coverage upgrades: 697 and the 699 rows
gain the wwstage leg the carriers gated or skipped, and all positive
rows enter the blanket test-data-byteid net.
This commit is contained in:
@@ -1,10 +0,0 @@
|
||||
// modcollision/mod1 — exports `type stream` with mod1-shaped fields.
|
||||
// Paired with mod2/mod2.ww to exercise same-leaf-name cross-module
|
||||
// type disambiguation. Test driver: 696_modtype_leaf_collision.c.
|
||||
|
||||
package mod1;
|
||||
|
||||
export type stream = struct {
|
||||
a: i32,
|
||||
b: i32,
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
// modcollision/mod2 — exports `type stream` with mod2-shaped fields.
|
||||
// Paired with mod1/mod1.ww to exercise same-leaf-name cross-module
|
||||
// type disambiguation. Test driver: 696_modtype_leaf_collision.c.
|
||||
//
|
||||
// Fields are intentionally named distinctly from mod1's (c/d vs a/b)
|
||||
// so the negative test (`b: mod1.stream` accessed via mod2-only field
|
||||
// 'c') surfaces as a compile-time field-resolution error.
|
||||
|
||||
package mod2;
|
||||
|
||||
export type stream = struct {
|
||||
c: i32,
|
||||
d: i32,
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
// Negative case: declare `b: mod1.stream` then access a mod2-only
|
||||
// field. With the mod-tagged scope lookup `b` resolves to mod1.stream
|
||||
// (fields a, b), so the field access `b.c` must be a compile-time
|
||||
// error rather than silently binding to mod2.stream and succeeding.
|
||||
//
|
||||
// No cross-module call is made: a missing mod1.make would itself
|
||||
// trigger a link-time error that could mask the field-resolution
|
||||
// error this test is actually pinning. `let b: mod1.stream;` is
|
||||
// enough — we read b.c before initializing it, which is fine because
|
||||
// the field-resolution error fires at check, long before any reach
|
||||
// analysis or codegen runs.
|
||||
|
||||
package modcollision;
|
||||
|
||||
import mod1;
|
||||
import mod2;
|
||||
|
||||
fn main() i32 = {
|
||||
let b: mod1.stream;
|
||||
return b.c; // mod1.stream has no `c`; expect a compile error.
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
// Positive case: two modules each export `type stream`. The consumer
|
||||
// imports both and disambiguates via the module qualifier. mod1.stream
|
||||
// has fields (a, b); mod2.stream has fields (c, d). The exit code
|
||||
// encodes a sum of all four fields, so any cross-binding would either
|
||||
// fail to compile or return the wrong value.
|
||||
|
||||
package modcollision;
|
||||
|
||||
import mod1;
|
||||
import mod2;
|
||||
|
||||
fn main() i32 = {
|
||||
let s1: mod1.stream;
|
||||
s1.a = 3: i32;
|
||||
s1.b = 5: i32;
|
||||
let s2: mod2.stream;
|
||||
s2.c = 7: i32;
|
||||
s2.d = 11: i32;
|
||||
return s1.a + s1.b + s2.c + s2.d;
|
||||
};
|
||||
19
test/wcc/data/r696_modtype_leaf_neg/case.ww
Normal file
19
test/wcc/data/r696_modtype_leaf_neg/case.ww
Normal file
@@ -0,0 +1,19 @@
|
||||
//ww:error c "no field 'c' in stream" ww "asserttyped: dot"
|
||||
// migrated from test/wcc/696_modtype_leaf_collision.c: field `c` lives only on mod2.stream; pre-fix the read silently bound through the wrong type.
|
||||
package mod1;
|
||||
export type stream = struct {
|
||||
a: i32,
|
||||
b: i32,
|
||||
};
|
||||
package mod2;
|
||||
export type stream = struct {
|
||||
c: i32,
|
||||
d: i32,
|
||||
};
|
||||
package main;
|
||||
import mod1;
|
||||
import mod2;
|
||||
fn main() i32 = {
|
||||
let b: mod1.stream;
|
||||
return b.c;
|
||||
};
|
||||
24
test/wcc/data/r696_modtype_leaf_pos/case.ww
Normal file
24
test/wcc/data/r696_modtype_leaf_pos/case.ww
Normal file
@@ -0,0 +1,24 @@
|
||||
//ww:run-exit 26
|
||||
// migrated from test/wcc/696_modtype_leaf_collision.c: same-leaf cross-module `type stream` must stay mod-tagged (pre-fix sym smash cross-bound the fields).
|
||||
package mod1;
|
||||
export type stream = struct {
|
||||
a: i32,
|
||||
b: i32,
|
||||
};
|
||||
package mod2;
|
||||
export type stream = struct {
|
||||
c: i32,
|
||||
d: i32,
|
||||
};
|
||||
package main;
|
||||
import mod1;
|
||||
import mod2;
|
||||
fn main() i32 = {
|
||||
let s1: mod1.stream;
|
||||
s1.a = 3: i32;
|
||||
s1.b = 5: i32;
|
||||
let s2: mod2.stream;
|
||||
s2.c = 7: i32;
|
||||
s2.d = 11: i32;
|
||||
return s1.a + s1.b + s2.c + s2.d;
|
||||
};
|
||||
22
test/wcc/data/r697_samemod_prefer/case.ww
Normal file
22
test/wcc/data/r697_samemod_prefer/case.ww
Normal file
@@ -0,0 +1,22 @@
|
||||
//ww:compile
|
||||
// migrated from test/wcc/697_samemod_prefer.c: bare-leaf `read` binds same-module first; compile-only (unmangled TEXT read labels still collapse in the linker).
|
||||
package mod1;
|
||||
export fn read(x: i32) i32 = {
|
||||
return x + 100i32;
|
||||
};
|
||||
export fn caller() i32 = {
|
||||
return read(1i32);
|
||||
};
|
||||
package mod2;
|
||||
export fn read(x: str) i32 = {
|
||||
return x.len + 200i32;
|
||||
};
|
||||
export fn caller() i32 = {
|
||||
return read("ok");
|
||||
};
|
||||
package main;
|
||||
import mod1;
|
||||
import mod2;
|
||||
fn main() i32 = {
|
||||
return 0i32;
|
||||
};
|
||||
14
test/wcc/data/r699_usepromote_def/case.ww
Normal file
14
test/wcc/data/r699_usepromote_def/case.ww
Normal file
@@ -0,0 +1,14 @@
|
||||
//ww:run-exit 42
|
||||
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_DEF promotion must keep use_alias so `defmod.flag` resolves.
|
||||
package defmod;
|
||||
export def defmod: i32 = 0i32;
|
||||
export type flag = enum i32 {
|
||||
NONE = 0,
|
||||
A = 42,
|
||||
};
|
||||
package main;
|
||||
import defmod;
|
||||
fn main() i32 = {
|
||||
let m: defmod.flag = defmod.flag.A;
|
||||
return m: i32;
|
||||
};
|
||||
16
test/wcc/data/r699_usepromote_fn/case.ww
Normal file
16
test/wcc/data/r699_usepromote_fn/case.ww
Normal file
@@ -0,0 +1,16 @@
|
||||
//ww:run-exit 42
|
||||
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_FN promotion (the original bug) must keep use_alias or `fnmod.flag` fails "unknown type".
|
||||
package fnmod;
|
||||
export type flag = enum i32 {
|
||||
NONE = 0,
|
||||
A = 42,
|
||||
};
|
||||
export fn fnmod() i32 = {
|
||||
return 0i32;
|
||||
};
|
||||
package main;
|
||||
import fnmod;
|
||||
fn main() i32 = {
|
||||
let m: fnmod.flag = fnmod.flag.A;
|
||||
return m: i32;
|
||||
};
|
||||
16
test/wcc/data/r699_usepromote_type/case.ww
Normal file
16
test/wcc/data/r699_usepromote_type/case.ww
Normal file
@@ -0,0 +1,16 @@
|
||||
//ww:run-exit 42
|
||||
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_TYPE in-place promotion keeps use_alias so `typmod.flag` resolves (check.c self-import branch).
|
||||
package typmod;
|
||||
export type typmod = struct {
|
||||
x: i32,
|
||||
};
|
||||
export type flag = enum i32 {
|
||||
NONE = 0,
|
||||
A = 42,
|
||||
};
|
||||
package main;
|
||||
import typmod;
|
||||
fn main() i32 = {
|
||||
let m: typmod.flag = typmod.flag.A;
|
||||
return m: i32;
|
||||
};
|
||||
14
test/wcc/data/r699_usepromote_var/case.ww
Normal file
14
test/wcc/data/r699_usepromote_var/case.ww
Normal file
@@ -0,0 +1,14 @@
|
||||
//ww:run-exit 42
|
||||
// migrated from test/wcc/699_use_promote_alias.c: SK_USE->SK_VAR promotion must keep use_alias so `varmod.flag` resolves.
|
||||
package varmod;
|
||||
export let varmod: i32 = 0i32;
|
||||
export type flag = enum i32 {
|
||||
NONE = 0,
|
||||
A = 42,
|
||||
};
|
||||
package main;
|
||||
import varmod;
|
||||
fn main() i32 = {
|
||||
let m: varmod.flag = varmod.flag.A;
|
||||
return m: i32;
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
// samemodprefer/mod1 — exports a `read` that takes an i32 plus a
|
||||
// `caller` that invokes bare `read(1i32)`. The bare-leaf lookup must
|
||||
// resolve to mod1.read (i32 → i32) rather than mod2.read (str → i32),
|
||||
// which coexists in the flat scope. Pre-fix the lookup picked
|
||||
// whichever entry hashed earliest into the bucket; a wrong bind would
|
||||
// surface as a check-time signature mismatch. Paired with mod2/mod2.ww
|
||||
// and test/wcc/697_samemod_prefer.c.
|
||||
|
||||
package mod1;
|
||||
|
||||
export fn read(x: i32) i32 = {
|
||||
return x + 100i32;
|
||||
};
|
||||
|
||||
export fn caller() i32 = {
|
||||
// Bare-leaf call inside mod1: must bind to mod1.read (i32 arg).
|
||||
// If preference doesn't kick in this fails check: mod2.read
|
||||
// expects a str, so `read(1i32)` would be a signature mismatch.
|
||||
return read(1i32);
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
// samemodprefer/mod2 — exports a `read` that takes a str plus a
|
||||
// `caller` that invokes bare `read("ok")`. The bare-leaf lookup must
|
||||
// resolve to mod2.read (str → i32) rather than mod1.read (i32 → i32),
|
||||
// which coexists in the flat scope. Pre-fix the lookup picked
|
||||
// whichever entry hashed earliest into the bucket; a wrong bind would
|
||||
// surface as a check-time signature mismatch. Paired with mod1/mod1.ww
|
||||
// and test/wcc/697_samemod_prefer.c.
|
||||
|
||||
package mod2;
|
||||
|
||||
export fn read(x: str) i32 = {
|
||||
return x.len + 200i32;
|
||||
};
|
||||
|
||||
export fn caller() i32 = {
|
||||
// Bare-leaf call inside mod2: must bind to mod2.read (str arg).
|
||||
// If preference doesn't kick in this fails check: mod1.read
|
||||
// expects an i32, so `read("ok")` would be a signature mismatch.
|
||||
return read("ok");
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
// Positive case: two modules each export `read` with DIFFERENT
|
||||
// signatures (mod1: i32 → i32, mod2: str → i32). Each module also
|
||||
// exports a `caller` that invokes bare `read(...)` with its own arg
|
||||
// type. The bare-leaf inside mod1 must bind to mod1.read; inside mod2
|
||||
// to mod2.read. If preference doesn't kick in and the bare lookup
|
||||
// picks the other module's `read`, the build fails with a signature
|
||||
// mismatch at check-time. The driver test asserts that this fixture
|
||||
// builds successfully.
|
||||
//
|
||||
// We don't assert runtime exit codes here because cgen still emits
|
||||
// unmangled `TEXT read` labels for both modules and the linker
|
||||
// collapses them — that's a separate codegen sweep, orthogonal to the
|
||||
// resolver fix this test pins.
|
||||
|
||||
package samemodprefer;
|
||||
|
||||
import mod1;
|
||||
import mod2;
|
||||
|
||||
fn main() i32 = {
|
||||
return 0i32;
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
// usepromote/defmod — exports a `def defmod` with the same leaf as
|
||||
// the module name. Paired with pos_def.ww to exercise the SK_USE→
|
||||
// SK_DEF promotion (cmd/wcc/check.c L1709). Mirrors the SK_FN bug
|
||||
// shape: without `use_alias = 1`, the consumer's `defmod.flag` lookup
|
||||
// fails because the promoted-in-place SK_DEF leaf no longer advertises
|
||||
// itself as a module head.
|
||||
|
||||
package defmod;
|
||||
|
||||
export def defmod: i32 = 0i32;
|
||||
|
||||
export type flag = enum i32 {
|
||||
NONE = 0,
|
||||
A = 42,
|
||||
};
|
||||
@@ -1,19 +0,0 @@
|
||||
// usepromote/fnmod — exports a `fn fnmod()` with the same leaf as the
|
||||
// module name. Paired with pos_fn.ww to exercise the bug fix at
|
||||
// cmd/wcc/check.c L1722 (SK_USE→SK_FN promotion was missing the
|
||||
// `use_alias = 1` line, so the consumer's `fnmod.flag` lookup walked
|
||||
// resolve_typename's dot branch, found head `fnmod` as SK_FN, and
|
||||
// skipped the module-filtered leaf path → "unknown type fnmod.flag".
|
||||
//
|
||||
// lib/fnmatch is the real-world instance that surfaced this.
|
||||
|
||||
package fnmod;
|
||||
|
||||
export type flag = enum i32 {
|
||||
NONE = 0,
|
||||
A = 42,
|
||||
};
|
||||
|
||||
export fn fnmod() i32 = {
|
||||
return 0i32;
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
// SK_USE→SK_DEF promotion. Same shape as pos_fn.ww but the imported
|
||||
// module exports `def defmod: i32 = 0` instead of `fn defmod()`.
|
||||
// Pass-1.5 N_DEF case (check.c L1709) promotes the SK_USE leaf to
|
||||
// SK_DEF. Pre-fix it forgot use_alias=1, so `defmod.flag` resolution
|
||||
// failed. Post-fix the build succeeds and exit code = flag.A = 42.
|
||||
|
||||
package usepromote;
|
||||
|
||||
import defmod;
|
||||
|
||||
fn main() i32 = {
|
||||
let m: defmod.flag = defmod.flag.A;
|
||||
return m: i32;
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
// SK_USE→SK_FN promotion (the bug). fnmod exports `fn fnmod()` and
|
||||
// `type flag = enum`. Pass-1 installs SK_TYPE("flag", mod="fnmod") and
|
||||
// SK_USE("fnmod") (the `fn fnmod` isn't installed in pass-1; pass-1
|
||||
// only handles N_USE + N_TYPEDECL). Pass-1.5 then sees the N_FNDECL
|
||||
// "fnmod", finds the SK_USE local, and promotes in place to SK_FN.
|
||||
// Pre-fix that promotion forgot `use_alias = 1`, so `fnmod.flag`
|
||||
// resolution failed with "unknown type fnmod.flag". Post-fix the
|
||||
// build succeeds and exit code = flag.A = 42.
|
||||
|
||||
package usepromote;
|
||||
|
||||
import fnmod;
|
||||
|
||||
fn main() i32 = {
|
||||
let m: fnmod.flag = fnmod.flag.A;
|
||||
return m: i32;
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
// SK_USE→SK_TYPE regression pin. typmod exports `type typmod = ...`
|
||||
// AND `type flag = enum`. Driver concatenation puts imported decls
|
||||
// first, so pass-1 installs SK_TYPE("typmod") first; the primary's
|
||||
// `use typmod` then hits the self-import branch (check.c L1660) and
|
||||
// sets use_alias=1 on the SK_TYPE entry. We rely on use_alias=1 here
|
||||
// so the dot-prefixed `typmod.flag` lookup resolves to mod="typmod"'s
|
||||
// flag entry. Exit code = flag.A = 42 verifies end-to-end.
|
||||
|
||||
package usepromote;
|
||||
|
||||
import typmod;
|
||||
|
||||
fn main() i32 = {
|
||||
let m: typmod.flag = typmod.flag.A;
|
||||
return m: i32;
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
// SK_USE→SK_VAR promotion. Imported module exports a top-level
|
||||
// `let varmod: i32 = 0`. Pass-1.5 N_LET case (check.c L1736) promotes
|
||||
// the SK_USE leaf to SK_VAR. Pre-fix it forgot use_alias=1, so
|
||||
// `varmod.flag` resolution failed. Post-fix the build succeeds and
|
||||
// exit code = flag.A = 42.
|
||||
|
||||
package usepromote;
|
||||
|
||||
import varmod;
|
||||
|
||||
fn main() i32 = {
|
||||
let m: varmod.flag = varmod.flag.A;
|
||||
return m: i32;
|
||||
};
|
||||
@@ -1,19 +0,0 @@
|
||||
// usepromote/typmod — exports a `type typmod` with the same leaf as
|
||||
// the module name. Paired with pos_type.ww to pin the SK_USE→SK_TYPE
|
||||
// promotion's use_alias=1 behaviour (cmd/wcc/check.c L1660 / L1677):
|
||||
// the consumer's `typmod.flag` lookup must walk through the alias
|
||||
// even though the leaf sym is SK_TYPE, not SK_USE.
|
||||
//
|
||||
// random.random in lib/ is the canonical real-world instance of this
|
||||
// shape; this fixture replays it as a regression pin.
|
||||
|
||||
package typmod;
|
||||
|
||||
export type typmod = struct {
|
||||
x: i32,
|
||||
};
|
||||
|
||||
export type flag = enum i32 {
|
||||
NONE = 0,
|
||||
A = 42,
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
// usepromote/varmod — exports a top-level `let varmod` with the same
|
||||
// leaf as the module name. Paired with pos_var.ww to exercise the
|
||||
// SK_USE→SK_VAR promotion at cmd/wcc/check.c L1736. Same shape as
|
||||
// SK_DEF / SK_FN — without `use_alias = 1`, the consumer's
|
||||
// `varmod.flag` lookup fails.
|
||||
|
||||
package varmod;
|
||||
|
||||
export let varmod: i32 = 0i32;
|
||||
|
||||
export type flag = enum i32 {
|
||||
NONE = 0,
|
||||
A = 42,
|
||||
};
|
||||
Reference in New Issue
Block a user