comments: drop retired lint markers, re-cite migrated carriers

peel-ok/sizelint-ok/primsize-ok annotations lose their tools; sites
keep the WHY in plain words. Citations of retired carriers move to
their fixture or @test successors (949_errtype_compare -> r949_*,
900_stdlib -> library owners).
This commit is contained in:
2026-08-07 23:03:55 +09:00
parent 228a632a2f
commit 90dc6369c9
12 changed files with 61 additions and 81 deletions

View File

@@ -770,10 +770,9 @@ nullable_ptr_tag(Type *t)
if (t == NULL || t->kind != TY_TAGGED) return 0; if (t == NULL || t->kind != TY_TAGGED) return 0;
int i = 0; int i = 0;
for (Tparam *p = t->params; p; p = p->next, i++) { for (Tparam *p = t->params; p; p = p->next, i++) {
/* peel-ok: single peel PROBE-CLEARED (batch-2 c3-B2, /* A single-level inspection is sufficient here (batch-2 c3-B2,
* 018ef66) constructible variant params never carry * 018ef66): constructible variant params never carry nested
* 2+-level NAMED at this scan; ww twin cgenutil.ww:2758 * NAMED layers at this scan; the ww twin uses the same invariant. */
* carries the identical annotated peel. */
Type *pu = (p->type && p->type->kind == TY_NAMED) Type *pu = (p->type && p->type->kind == TY_NAMED)
? p->type->under : p->type; ? p->type->under : p->type;
if (pu && pu->kind == TY_PTR) return i; if (pu && pu->kind == TY_PTR) return i;
@@ -849,7 +848,7 @@ cg_variant_match(Type *vt, Type *src)
* Sound only while the model is nominal-lossy; the collision * Sound only while the model is nominal-lossy; the collision
* guard at the widen site (cg_widen_tagged_store) enforces the * guard at the widen site (cg_widen_tagged_store) enforces the
* invariant for when #199b/B-full lands true nominal layout. * invariant for when #199b/B-full lands true nominal layout.
* peel-ok (#218, B5-c1): these single peels serve ONLY the * These single-level inspections serve ONLY the
* both-TAGGED structural fallback — a NAMED struct source vs * both-TAGGED structural fallback — a NAMED struct source vs
* a NAMED variant falls through every arm at ANY depth * a NAMED variant falls through every arm at ANY depth
* (.ai/ken-b5-oracle.md §4: kb5_v2s1i both-wrong-identical * (.ai/ken-b5-oracle.md §4: kb5_v2s1i both-wrong-identical
@@ -875,7 +874,7 @@ cg_variant_match(Type *vt, Type *src)
static int static int
cg_variant_struct_match(Type *vt, Type *src) cg_variant_struct_match(Type *vt, Type *src)
{ {
/* peel-ok (#218, B5-c1): shape-only collision count for the /* Shape-only collision count for the
* both-TAGGED fallback above — same probe record, task #95 * both-TAGGED fallback above — same probe record, task #95
* (.ai/ken-b5-oracle.md §4). */ * (.ai/ken-b5-oracle.md §4). */
Type *vu = (vt && vt->kind == TY_NAMED) ? vt->under : vt; Type *vu = (vt && vt->kind == TY_NAMED) ? vt->under : vt;

View File

@@ -105,7 +105,7 @@ resolve_typename(Checker *c, Node *n)
* handing its type out; no consumer may ever see the size-0 * handing its type out; no consumer may ever see the size-0
* placeholder. Mirrors wwstage's demand-driven tinfofornode, the * placeholder. Mirrors wwstage's demand-driven tinfofornode, the
* measured order-independent side. */ * measured order-independent side. */
/* peel-ok: under==NULL probes resolve state, not a dealias */ /* A missing underlying type is the unresolved-state marker. */
if (s->type && s->type->kind == TY_NAMED && s->type->under == NULL if (s->type && s->type->kind == TY_NAMED && s->type->under == NULL
&& s->decl && s->decl->kind == N_TYPEDECL) && s->decl && s->decl->kind == N_TYPEDECL)
resolve_typedecl(c, s->decl); resolve_typedecl(c, s->decl);
@@ -785,7 +785,7 @@ resolve_type(Checker *c, Node *n)
|| eu->kind == TY_TAGGED)) || eu->kind == TY_TAGGED))
sz += (eu->size + 7) & ~(u64)7; sz += (eu->size + 7) & ~(u64)7;
else if (eu == NULL || eu->kind != TY_VOID) else if (eu == NULL || eu->kind != TY_VOID)
sz += 8; /* sizelint-ok: the slot IS the 8B eightbyte */ sz += 8; /* Each scalar occupies one SysV eightbyte. */
} }
if (head == NULL) head = tp; if (head == NULL) head = tp;
else tail->next = tp; else tail->next = tp;
@@ -1073,8 +1073,8 @@ unify_arith(Checker *c, Pos p, Type *a, Type *b)
* a plain i32 — type_eq ignores iserror (primitives compare by * a plain i32 — type_eq ignores iserror (primitives compare by
* kind), but harec interns flags into DISTINCT types, so flagged- * kind), but harec interns flags into DISTINCT types, so flagged-
* vs-unflagged never reaches type_promote's dealias-equal arm. The * vs-unflagged never reaches type_promote's dealias-equal arm. The
* #246 loud (strconv.invalid != i32, pinned by 949_errtype_compare * #246 loud (strconv.invalid != i32, pinned by the r949_errtype_*
* on BOTH stages) rides this reject. */ * fixtures on BOTH stages) rides this reject. */
{ {
Type *da = type_chase_named(a); Type *da = type_chase_named(a);
Type *db = type_chase_named(b); Type *db = type_chase_named(b);
@@ -2371,7 +2371,7 @@ cexpr(Checker *c, Node *n)
|| eu->kind == TY_TAGGED)) || eu->kind == TY_TAGGED))
sz += (eu->size + 7) & ~(u64)7; sz += (eu->size + 7) & ~(u64)7;
else if (eu == NULL || eu->kind != TY_VOID) else if (eu == NULL || eu->kind != TY_VOID)
sz += 8; /* sizelint-ok: the slot IS the 8B eightbyte */ sz += 8; /* Each scalar occupies one SysV eightbyte. */
if (head == NULL) head = tp; if (head == NULL) head = tp;
else tail->next = tp; else tail->next = tp;
tail = tp; tail = tp;
@@ -2860,7 +2860,7 @@ static void
resolve_typedecl(Checker *c, Node *d) resolve_typedecl(Checker *c, Node *d)
{ {
Type *t = d->type; Type *t = d->type;
/* peel-ok: under!=NULL probes resolve state, not a dealias */ /* A present underlying type is the resolved-state marker. */
if (t == NULL || t->under != NULL || t->resolving) return; if (t == NULL || t->under != NULL || t->resolving) return;
t->resolving = 1; t->resolving = 1;
const char *save = c->cur_mod; const char *save = c->cur_mod;
@@ -2875,7 +2875,7 @@ resolve_typedecl(Checker *c, Node *d)
if (circular_named(c, under, d->pos)) if (circular_named(c, under, d->pos))
under = ty_err; under = ty_err;
t->resolving = 0; t->resolving = 0;
t->under = under; /* peel-ok: construction */ t->under = under;
if (under) { if (under) {
t->size = under->size; t->size = under->size;
t->align = under->align; t->align = under->align;

View File

@@ -75,7 +75,7 @@ typesinit(Arena *a)
* the same way a user-declared alias would. */ * the same way a user-declared alias would. */
ty_nomem = newtype(a, TY_NAMED); ty_nomem = newtype(a, TY_NAMED);
ty_nomem->name = "nomem"; ty_nomem->name = "nomem";
ty_nomem->under = ty_void; /* peel-ok: construction */ ty_nomem->under = ty_void;
ty_nomem->size = ty_void->size; ty_nomem->size = ty_void->size;
ty_nomem->align = ty_void->align; ty_nomem->align = ty_void->align;
ty_nomem->iserror = 1; ty_nomem->iserror = 1;
@@ -107,7 +107,7 @@ type_slice(Arena *a, Type *sub)
{ {
Type *t = newtype(a, TY_SLICE); Type *t = newtype(a, TY_SLICE);
t->sub = sub; t->sub = sub;
t->size = 24; /* { *T, len, cap } */ /* sizelint-ok: SSoT for ty_slice (#64) */ t->size = 24; /* Slice headers carry pointer, length, and capacity. */
t->align = 8; t->align = 8;
return t; return t;
} }
@@ -138,7 +138,7 @@ type_named(Arena *a, const char *name, Type *under)
{ {
Type *t = newtype(a, TY_NAMED); Type *t = newtype(a, TY_NAMED);
t->name = name; t->name = name;
t->under = under; /* peel-ok: construction */ t->under = under;
if (under) { if (under) {
t->size = under->size; t->size = under->size;
t->align = under->align; t->align = under->align;
@@ -159,7 +159,7 @@ type_named(Arena *a, const char *name, Type *under)
Type * Type *
type_chase_named(Type *t) type_chase_named(Type *t)
{ {
while (t && t->kind == TY_NAMED) t = t->under; /* peel-ok: chase body */ while (t && t->kind == TY_NAMED) t = t->under;
return t; return t;
} }
@@ -176,7 +176,7 @@ type_isint(Type *t)
case TY_UNTYPED_RUNE: case TY_UNTYPED_RUNE:
return 1; return 1;
case TY_ENUM: return type_isint(t->sub); case TY_ENUM: return type_isint(t->sub);
case TY_NAMED: /* peel-ok: recursive chase */ case TY_NAMED:
return type_isint(t->under); return type_isint(t->under);
default: return 0; default: return 0;
} }
@@ -189,7 +189,7 @@ type_isfloat(Type *t)
switch (t->kind) { switch (t->kind) {
case TY_F32: case TY_F64: case TY_UNTYPED_FLOAT: case TY_F32: case TY_F64: case TY_UNTYPED_FLOAT:
return 1; return 1;
case TY_NAMED: /* peel-ok: recursive chase */ case TY_NAMED:
return type_isfloat(t->under); return type_isfloat(t->under);
default: return 0; default: return 0;
} }
@@ -210,7 +210,7 @@ type_isunsigned(Type *t)
case TY_UINT: case TY_UINTPTR: case TY_SIZE: case TY_UINT: case TY_UINTPTR: case TY_SIZE:
case TY_RUNE: case TY_RUNE:
return 1; return 1;
case TY_NAMED: /* peel-ok: recursive chase */ case TY_NAMED:
return type_isunsigned(t->under); return type_isunsigned(t->under);
case TY_ENUM: return type_isunsigned(t->sub); case TY_ENUM: return type_isunsigned(t->sub);
default: return 0; default: return 0;

View File

@@ -201,10 +201,8 @@ fn check_str(name: str, input: str, want: str, ep: **env) void = {
}; };
}; };
// strconv.f64tos probes. We run them through lisp_test rather than a // strconv.f64tos probes. Library-owned strconv tests cover formatting;
// standalone strconv test program because there's no stdlib-test // these rows retain the application-level consumer expectations here.
// scaffolding yet (cf. test/wcc/900_stdlib.c which only checks
// modules compile, not behaviour). Move out when that lands.
fn check_f64tos(name: str, v: f64, want: str) void = { fn check_f64tos(name: str, v: f64, want: str) void = {
ntotal += 1; ntotal += 1;
let s: str = strconv.f64tos(v); let s: str = strconv.f64tos(v);

View File

@@ -22,8 +22,8 @@
// (io fold-2, #5), so the dispatchers ARE the public // (io fold-2, #5), so the dispatchers ARE the public
// surface and grow the `handle` match when #5 lands. // surface and grow the `handle` match when #5 lands.
// empty the discard+EOF stream (ref/hare/io/empty.ha:13). Lives // empty the discard+EOF stream (ref/hare/io/empty.ha:13). Lives
// here rather than io.ww so that 900_stdlib can compile // here rather than io.ww so io.ww remains a standalone
// io.ww standalone (io.ww has no cross-file type refs). // frontend input with no cross-file type references.
// //
// Deferrals (drew-signed): `seeker` lands with io fold-2 (#5) once `off` // Deferrals (drew-signed): `seeker` lands with io fold-2 (#5) once `off`
// + `whence` plug into the signature. Hare's `?`-propagating `close` // + `whence` plug into the signature. Hare's `?`-propagating `close`
@@ -196,8 +196,8 @@ export fn tell(h: handle) (off | error) = {
// vtable is a module-level `let` and [[empty]] is a function that wires // vtable is a module-level `let` and [[empty]] is a function that wires
// the fn-ptr slots on every call and returns the stream pointer. // the fn-ptr slots on every call and returns the stream pointer.
// Single-assignment on the same words: idempotent under re-entry. // Single-assignment on the same words: idempotent under re-entry.
// Lives in stream.ww (not io.ww) so that 900_stdlib can compile io.ww // Lives in stream.ww (not io.ww) so io.ww stays standalone without
// standalone without referencing the cross-file vtable/reader/writer types. // referencing the cross-file vtable/reader/writer types.
fn _empty_read(s: stream, buf: []u8) (size | eof | error) = { fn _empty_read(s: stream, buf: []u8) (size | eof | error) = {
let e: eof; let e: eof;

View File

@@ -10,12 +10,13 @@
// the non-T @test drop, #6). Load-bearing ww-compiler coverage (drove // the non-T @test drop, #6). Load-bearing ww-compiler coverage (drove
// #34/#38/#44/#45/#48), not black-box-reachable. // #34/#38/#44/#45/#48), not black-box-reachable.
// //
// `_whitebox.ww` (NOT *_test.ww) keeps this file in the production // This noncanonical `_whitebox.ww` name is retained during migration. The
// enumerator's root-package assembly until package-aware testing can classify // package planner's explicit compatibility rule recognizes its line-leading
// same-package `*_test.ww` files (T1). The T0 gate resolves `regex` as the root // @test declarations and assembles it with the production `regex` sources;
// directory so -T sees these tests directly; importing regex as a dependency // ordinary production files merely ending in `test.ww` stay production.
// would strip them. Public-API tests remain a separate `package regex_test` // Importing regex as a dependency still strips these tests. Public-API tests
// binary in lib/regex/regex_test.ww (CLAUDE.md rule 9). // remain a separate `package regex_test` binary in lib/regex/regex_test.ww
// (CLAUDE.md rule 9).
package regex; package regex;
import io; import io;

View File

@@ -5,8 +5,8 @@
// //
// Hare splits this across types.ha/search.ha/bisect.ha; ww merges a // Hare splits this across types.ha/search.ha/bisect.ha; ww merges a
// module into one file (same convention as lib/types/types.ww merging // module into one file (same convention as lib/types/types.ww merging
// Hare's limits.ha + arch+x86_64.ha), and 900_stdlib smoke-compiles // Hare's limits.ha + arch+x86_64.ha). test/wcc/963_sort_run.c compiles
// lib/sort/sort.ww standalone, which a split would break. // and executes this sole-source package directly.
// //
// Divergences from the Hare source, all forced by ww's surface (not // Divergences from the Hare source, all forced by ww's surface (not
// behavioural — rule-10 align-down): // behavioural — rule-10 align-down):

View File

@@ -280,9 +280,10 @@ export fn typeptr(sub: *tinfo) *tinfo = {
export fn typeslice(sub: *tinfo) *tinfo = { export fn typeslice(sub: *tinfo) *tinfo = {
let t: *tinfo = newtype(tykind.TY_SLICE); let t: *tinfo = newtype(tykind.TY_SLICE);
t.sub = sub; t.sub = sub;
t.size = 24u64; // sizelint-ok: SSoT for slice header (#64) // Slice headers carry pointer, length, and capacity (#64).
t.size = 24u64;
t.align = 8u64; t.align = 8u64;
t.slotsize = 24u64; // sizelint-ok: SSoT for slice slotsize (#64) t.slotsize = 24u64;
return t; return t;
}; };
@@ -316,7 +317,7 @@ export fn typechan(sub: *tinfo) *tinfo = {
export fn typenamed(name: str, under: *tinfo) *tinfo = { export fn typenamed(name: str, under: *tinfo) *tinfo = {
let t: *tinfo = newtype(tykind.TY_NAMED); let t: *tinfo = newtype(tykind.TY_NAMED);
t.name = name; t.name = name;
t.under = under; // peel-ok: construction t.under = under;
if (under != nil) { if (under != nil) {
t.size = under.size; t.size = under.size;
t.align = under.align; t.align = under.align;
@@ -373,7 +374,6 @@ export fn typeisint(t: *tinfo) bool = {
if (k == tykind.TY_UNTYPED_INT) { return true; }; if (k == tykind.TY_UNTYPED_INT) { return true; };
if (k == tykind.TY_UNTYPED_RUNE) { return true; }; if (k == tykind.TY_UNTYPED_RUNE) { return true; };
if (k == tykind.TY_ENUM) { return typeisint(t.sub); }; if (k == tykind.TY_ENUM) { return typeisint(t.sub); };
// peel-ok: recursive chase
if (k == tykind.TY_NAMED) { return typeisint(t.under); }; if (k == tykind.TY_NAMED) { return typeisint(t.under); };
return false; return false;
}; };
@@ -384,7 +384,6 @@ export fn typeisfloat(t: *tinfo) bool = {
if (k == tykind.TY_F32) { return true; }; if (k == tykind.TY_F32) { return true; };
if (k == tykind.TY_F64) { return true; }; if (k == tykind.TY_F64) { return true; };
if (k == tykind.TY_UNTYPED_FLOAT) { return true; }; if (k == tykind.TY_UNTYPED_FLOAT) { return true; };
// peel-ok: recursive chase
if (k == tykind.TY_NAMED) { return typeisfloat(t.under); }; if (k == tykind.TY_NAMED) { return typeisfloat(t.under); };
return false; return false;
}; };
@@ -409,7 +408,6 @@ export fn typeisunsigned(t: *tinfo) bool = {
if (k == tykind.TY_UINTPTR) { return true; }; if (k == tykind.TY_UINTPTR) { return true; };
if (k == tykind.TY_SIZE) { return true; }; if (k == tykind.TY_SIZE) { return true; };
if (k == tykind.TY_RUNE){ return true; }; if (k == tykind.TY_RUNE){ return true; };
// peel-ok: recursive chase
if (k == tykind.TY_NAMED) { return typeisunsigned(t.under); }; if (k == tykind.TY_NAMED) { return typeisunsigned(t.under); };
if (k == tykind.TY_ENUM) { return typeisunsigned(t.sub); }; if (k == tykind.TY_ENUM) { return typeisunsigned(t.sub); };
return false; return false;
@@ -436,7 +434,6 @@ export fn typeisstr(t: *tinfo) bool = {
let k: tykind = t.kind; let k: tykind = t.kind;
if (k == tykind.TY_STR) { return true; }; if (k == tykind.TY_STR) { return true; };
if (k == tykind.TY_UNTYPED_STR) { return true; }; if (k == tykind.TY_UNTYPED_STR) { return true; };
// peel-ok: recursive chase
if (k == tykind.TY_NAMED) { return typeisstr(t.under); }; if (k == tykind.TY_NAMED) { return typeisstr(t.under); };
return false; return false;
}; };
@@ -446,7 +443,6 @@ export fn typeisslice(t: *tinfo) bool = {
if (t == nil) { return false; }; if (t == nil) { return false; };
let k: tykind = t.kind; let k: tykind = t.kind;
if (k == tykind.TY_SLICE) { return true; }; if (k == tykind.TY_SLICE) { return true; };
// peel-ok: recursive chase
if (k == tykind.TY_NAMED) { return typeisslice(t.under); }; if (k == tykind.TY_NAMED) { return typeisslice(t.under); };
return false; return false;
}; };
@@ -462,7 +458,6 @@ export fn typeistagged(t: *tinfo) bool = {
if (t == nil) { return false; }; if (t == nil) { return false; };
let k: tykind = t.kind; let k: tykind = t.kind;
if (k == tykind.TY_TAGGED) { return true; }; if (k == tykind.TY_TAGGED) { return true; };
// peel-ok: recursive chase
if (k == tykind.TY_NAMED) { return typeistagged(t.under); }; if (k == tykind.TY_NAMED) { return typeistagged(t.under); };
return false; return false;
}; };
@@ -474,7 +469,6 @@ export fn typeisf32(t: *tinfo) bool = {
if (t == nil) { return false; }; if (t == nil) { return false; };
let k: tykind = t.kind; let k: tykind = t.kind;
if (k == tykind.TY_F32) { return true; }; if (k == tykind.TY_F32) { return true; };
// peel-ok: recursive chase
if (k == tykind.TY_NAMED) { return typeisf32(t.under); }; if (k == tykind.TY_NAMED) { return typeisf32(t.under); };
return false; return false;
}; };
@@ -487,7 +481,6 @@ export fn typeisnullable(t: *tinfo) bool = {
if (t == nil) { return false; }; if (t == nil) { return false; };
let k: tykind = t.kind; let k: tykind = t.kind;
if (k == tykind.TY_TAGGED) { return t.nullable != 0; }; if (k == tykind.TY_TAGGED) { return t.nullable != 0; };
// peel-ok: recursive chase
if (k == tykind.TY_NAMED) { return typeisnullable(t.under); }; if (k == tykind.TY_NAMED) { return typeisnullable(t.under); };
return false; return false;
}; };
@@ -513,7 +506,6 @@ export fn typeis8byteprim(t: *tinfo) bool = {
if (k == tykind.TY_STR) { return false; }; if (k == tykind.TY_STR) { return false; };
if (k == tykind.TY_STRUCT) { return false; }; if (k == tykind.TY_STRUCT) { return false; };
if (k == tykind.TY_ARRAY) { return t.size == 8u64; }; if (k == tykind.TY_ARRAY) { return t.size == 8u64; };
// peel-ok: recursive chase
if (k == tykind.TY_NAMED) { return typeis8byteprim(t.under); }; if (k == tykind.TY_NAMED) { return typeis8byteprim(t.under); };
// Remaining: primitives (i8/u8/.../i64/u64/bool/rune/f32/f64/ // Remaining: primitives (i8/u8/.../i64/u64/bool/rune/f32/f64/
// int/uint/uintptr) and TY_VOID. All slot-pad to 8 and zero-init // int/uint/uintptr) and TY_VOID. All slot-pad to 8 and zero-init

View File

@@ -1049,7 +1049,7 @@ fn cgcast(c: *cgen, n: *syntax.node) void = {
else { if (lk == syntax.nkind.N_TENUM) { leaf_tn = leaf_tn.lhs; } else { if (lk == syntax.nkind.N_TENUM) { leaf_tn = leaf_tn.lhs; }
else { if (lk == syntax.nkind.N_TNAME) { else { if (lk == syntax.nkind.N_TNAME) {
let lnm: str = leaf_tn.str; let lnm: str = leaf_tn.str;
// primsize-ok (#101/#109): this IS an alias chase loop // This is an alias chase loop
// — primsize is the leaf-primitive break test the loop // — primsize is the leaf-primitive break test the loop
// wraps (aliaslookup advances the cursor on a miss). // wraps (aliaslookup advances the cursor on a miss).
if (primsize(lnm) > 0) { break; }; if (primsize(lnm) > 0) { break; };
@@ -8936,7 +8936,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
else { if (syntax.streq(pe.str, "f64")) { elemfloat = true; } else { if (syntax.streq(pe.str, "f64")) { elemfloat = true; }
else { if (syntax.streq(pe.str, "f32")) { elemfloat = true; elemf32 = true; } else { if (syntax.streq(pe.str, "f32")) { elemfloat = true; elemf32 = true; }
else { else {
// primsize-ok (#101/#109): this site OWNS its own ps==0 // This site owns its own ps==0
// typenodeprimresolved chase below — routing through // typenodeprimresolved chase below — routing through
// aliasprimsize would double-resolve and regress #11. // aliasprimsize would double-resolve and regress #11.
let ps: i32 = primsize(pe.str); let ps: i32 = primsize(pe.str);
@@ -13174,5 +13174,3 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
// The tail goes loud for the remaining kinds with #22. // The tail goes loud for the remaining kinds with #22.
return; return;
}; };

View File

@@ -3664,7 +3664,7 @@ fn paramfieldsize(t: *syntax.node) i32 = {
if (k == syntax.nkind.N_TNAME) { if (k == syntax.nkind.N_TNAME) {
let nm: str = t.str; let nm: str = t.str;
if (syntax.streq(nm, "str")) { return primtypesize("str"): i32; }; if (syntax.streq(nm, "str")) { return primtypesize("str"): i32; };
// primsize-ok (#101/#109): paramfieldsize is a STRUCTURAL // paramfieldsize is a STRUCTURAL
// (no-`c`, no-chase) sizer by design — it takes a *node, not a // (no-`c`, no-chase) sizer by design — it takes a *node, not a
// *cgen, so it cannot run aliasprimsize's aliaslookup chase // *cgen, so it cannot run aliasprimsize's aliaslookup chase
// (threading c is the dormant #110). A bare primsize is correct // (threading c is the dormant #110). A bare primsize is correct

View File

@@ -1600,16 +1600,12 @@ fn elemisarrayc(c: *cgen, t: *syntax.node) bool = {
return elem.kind == syntax.nkind.N_TARRAY; return elem.kind == syntax.nkind.N_TARRAY;
}; };
// tichase — transitive TY_NAMED peel, nil-passthrough. Exact wwstage // tichase is the wwstage twin of cstage type_chase_named
// twin of cstage type_chase_named (cmd/wcc/type.c:160-162, alias arc // (cmd/wcc/type.c:160-162, alias arc #5). Alias chains stack TY_NAMED
// #5): chain-of-aliases stacks TY_NAMED layers, so any single peel // layers, so consumers that need structural shape must resolve the whole
// leaves a kind-gated consumer staring at TY_NAMED and falling to a // chain or risk the scalar fallback (#60's esz=1/pointer-base family).
// scalar shape (#60's esz=1/pointer-base SEGV family). One chased
// accessor is the only spelled way to dealias; raw `.under` reads
// outside it are the lint target (rob F2 ruling).
fn tichase(t0: *syntax.tinfo) *syntax.tinfo = { fn tichase(t0: *syntax.tinfo) *syntax.tinfo = {
let t: *syntax.tinfo = t0; let t: *syntax.tinfo = t0;
// peel-ok: chase body
for (t != nil && t.kind == syntax.tykind.TY_NAMED) { t = t.under; }; for (t != nil && t.kind == syntax.tykind.TY_NAMED) { t = t.under; };
return t; return t;
}; };
@@ -1796,7 +1792,7 @@ fn elemsizeof(t: *syntax.node) i32 = {
// reads eff->sub->size (cmd/w6c/cgen.c N_INDEX). // reads eff->sub->size (cmd/w6c/cgen.c N_INDEX).
if (syntax.streq(nm, "str")) { return primtypesize("u8"): i32; }; if (syntax.streq(nm, "str")) { return primtypesize("u8"): i32; };
// Indexing a primitive name (rare): element size = the prim. // Indexing a primitive name (rare): element size = the prim.
// primsize-ok (#101/#109): elemsizeof is the STRUCTURAL (non- // elemsizeof is the STRUCTURAL (non-
// chasing) sizer by design — its alias-resolving twin elemsizeofc // chasing) sizer by design — its alias-resolving twin elemsizeofc
// owns the chase (routed through aliasprimsize at the :1579 leg). // owns the chase (routed through aliasprimsize at the :1579 leg).
// A bare primsize here is correct, not the #101 bug shape. // A bare primsize here is correct, not the #101 bug shape.
@@ -1824,7 +1820,7 @@ fn elemsizeof(t: *syntax.node) i32 = {
let nm: str = elem.str; let nm: str = elem.str;
// str element is 16B (ptr+len). primsize returns 0 for it. // str element is 16B (ptr+len). primsize returns 0 for it.
if (syntax.streq(nm, "str")) { return primtypesize("str"): i32; }; if (syntax.streq(nm, "str")) { return primtypesize("str"): i32; };
// primsize-ok (#101/#109): structural sizer — the chase lives // This structural sizer leaves alias resolution
// in elemsizeofc (:1579), not here. See the :1475 leg. // in elemsizeofc (:1579), not here. See the :1475 leg.
let ps: i32 = primsize(nm); let ps: i32 = primsize(nm);
if (ps > 0) { return ps; }; if (ps > 0) { return ps; };
@@ -2427,9 +2423,8 @@ fn fldnumidx(s: str) i32 = {
return r; return r;
}; };
// primsize-ok (#101/#109): the primitive-width oracle itself — this // This primitive-width oracle is the SSoT table aliasprimsize wraps;
// IS the SSoT table aliasprimsize wraps; there is nothing below it to // there is nothing below it to chase (#101/#109).
// chase.
fn primsize(name: str) i32 = { fn primsize(name: str) i32 = {
if (syntax.streq(name, "u8")) { return 1; }; if (syntax.streq(name, "u8")) { return 1; };
if (syntax.streq(name, "i8")) { return 1; }; if (syntax.streq(name, "i8")) { return 1; };
@@ -2463,8 +2458,8 @@ fn primsize(name: str) i32 = {
// at the twin sites; this is the ww align-up. The bare-primsize GUARD // at the twin sites; this is the ww align-up. The bare-primsize GUARD
// family (is-primitive dispatch) is the #109 follow-on, NOT routed // family (is-primitive dispatch) is the #109 follow-on, NOT routed
// here. #101. // here. #101.
// primsize-ok (#101/#109): the SSoT chase body itself — primsize is // primsize is the leaf-primitive probe this SSoT helper wraps, then
// the leaf-primitive probe this helper wraps, then aliaslookup chases. // aliaslookup chases (#101/#109).
fn aliasprimsize(c: *cgen, nm: str) i32 = { fn aliasprimsize(c: *cgen, nm: str) i32 = {
let ps: i32 = primsize(nm); let ps: i32 = primsize(nm);
if (ps > 0) { return ps; }; if (ps > 0) { return ps; };
@@ -2506,7 +2501,7 @@ export fn typenodeprimresolved(c: *cgen, t: *syntax.node,
// dedicated `is_bool` path in cgcast owns bool→bool's // dedicated `is_bool` path in cgcast owns bool→bool's
// ANDQ $255 on both stages. // ANDQ $255 on both stages.
if (syntax.streq(nm, "bool")) { return; }; if (syntax.streq(nm, "bool")) { return; };
// primsize-ok (#101/#109): this fn IS a prim-resolver // This function is a primitive resolver
// chaser (#33) — primsize is the leaf-primitive probe; // chaser (#33) — primsize is the leaf-primitive probe;
// aliaslookup below advances the walk on a miss. // aliaslookup below advances the walk on a miss.
let ps: i32 = primsize(nm); let ps: i32 = primsize(nm);
@@ -2546,7 +2541,7 @@ export fn exprprimresolved(c: *cgen, n: *syntax.node,
// mymode;` (mymode = enum u32). // mymode;` (mymode = enum u32).
let s: str = n.tsuffix; let s: str = n.tsuffix;
if (s.len > 0) { if (s.len > 0) {
// primsize-ok (#101/#109): a typed-int literal suffix // A typed-int literal suffix
// (`7u32`) is a builtin primitive name by grammar — no // (`7u32`) is a builtin primitive name by grammar — no
// alias can reach here, so there is nothing to chase. // alias can reach here, so there is nothing to chase.
let ps: i32 = primsize(s); let ps: i32 = primsize(s);
@@ -3110,8 +3105,8 @@ fn taggedmemargsize(t: *syntax.tinfo) i32 = {
if (u == nil) { return 0; }; if (u == nil) { return 0; };
if (u.kind != syntax.tykind.TY_TAGGED) { return 0; }; if (u.kind != syntax.tykind.TY_TAGGED) { return 0; };
if (u.nullable != 0) { return 0; }; if (u.nullable != 0) { return 0; };
// sizelint-ok: 6 SysV int arg regs (DI..R9) x 8B words — the // SysV supplies 6 integer argument registers (DI..R9); the 8-byte
// same register-capacity constant as cstage tagged_arg_size. // words below encode the same capacity as cstage tagged_arg_size.
if (u.size: i32 <= 6 * 8) { return 0; }; if (u.size: i32 <= 6 * 8) { return 0; };
return u.size: i32; return u.size: i32;
}; };
@@ -3325,10 +3320,10 @@ export fn nullableptrtag(t: *syntax.node) i32 = {
for (p != nil) { for (p != nil) {
let vt: *syntax.tinfo = p.type_; let vt: *syntax.tinfo = p.type_;
if (vt != nil) { if (vt != nil) {
// peel-ok: single peel PROBE-CLEARED (batch-2 c3-B2, // A single-level inspection is sufficient here (batch-2
// 018ef66) constructible variant params never carry // c3-B2, 018ef66): constructible variant params never carry
// 2+-level NAMED at this scan; cs twin nullable_ptr_tag // nested NAMED layers at this scan; the cs twin relies on
// (cmd/w6c/cgen.c:747) keeps the identical single peel. // the same invariant.
if (vt.kind == syntax.tykind.TY_NAMED) { vt = vt.under; }; if (vt.kind == syntax.tykind.TY_NAMED) { vt = vt.under; };
if (vt != nil) { if (vt != nil) {
if (vt.kind == syntax.tykind.TY_PTR) { return i; }; if (vt.kind == syntax.tykind.TY_PTR) { return i; };

View File

@@ -1254,7 +1254,7 @@ fn primtypesize(nm: str) i64 = {
// #43: SSoT for slice header size (ptr+len+cap = 24B today). Mirrors // #43: SSoT for slice header size (ptr+len+cap = 24B today). Mirrors
// cstage cmd/wcc/type.c:103 (ty_slice->size = 24). Bumping a slice's // cstage cmd/wcc/type.c:103 (ty_slice->size = 24). Bumping a slice's
// header layout in #34 touches only this constant. // header layout in #34 touches only this constant.
fn tyslicesize() i64 = { return 24i64; }; // sizelint-ok: SSoT for ty_slice header (#64) fn tyslicesize() i64 = { return 24i64; };
// #42: AST-level layout helpers for the size(T)/align(T)/offset(e.f) // #42: AST-level layout helpers for the size(T)/align(T)/offset(e.f)
// fold. Mirror cstage resolve_type's size/align computation // fold. Mirror cstage resolve_type's size/align computation
@@ -2226,9 +2226,6 @@ fn tinfofornode(c: *checker, n: *syntax.node) *syntax.tinfo = {
under = c.tc.tyerr; under = c.tc.tyerr;
}; };
named.resolving = 0; named.resolving = 0;
// peellint-ok: construction — the one
// WRITE that builds the NAMED link;
// not a peel, can't route via tichase.
named.under = under; named.under = under;
if (under != nil) { if (under != nil) {
named.size = under.size; named.size = under.size;
@@ -2663,7 +2660,7 @@ fn unifyarith(c: *checker, e: *syntax.node, ltn: *syntax.node, rtn: *syntax.node
// agree. Mirrors cstage unify_arith (cmd/wcc/check.c:1060-1067) and // agree. Mirrors cstage unify_arith (cmd/wcc/check.c:1060-1067) and
// harec type_promote (ref/harec/src/check.c:1083-1105). The error // harec type_promote (ref/harec/src/check.c:1083-1105). The error
// axis (varianterr) must agree on both sides so a `!i32` alias does // axis (varianterr) must agree on both sides so a `!i32` alias does
// NOT promote against a plain i32 (#246, 949_errtype_compare). // NOT promote against a plain i32 (#246, r949_errtype_* fixtures).
// A user alias is an SK_TYPE sym WITH a decl body; the primitives are // A user alias is an SK_TYPE sym WITH a decl body; the primitives are
// SK_TYPE too but decl == nil (check.ww:95-112), so aliassym alone // SK_TYPE too but decl == nil (check.ww:95-112), so aliassym alone
// would mis-flag i32 as "named". This decl != nil gate is the wwstage // would mis-flag i32 as "named". This decl != nil gate is the wwstage