diff --git a/cmd/wcc/lex.c b/cmd/wcc/lex.c index e7236184..46b2d940 100644 --- a/cmd/wcc/lex.c +++ b/cmd/wcc/lex.c @@ -95,6 +95,23 @@ skipws(Lex *l) } if (c == '/' && lpeek(l, 1) == '/') { lget(l); lget(l); /* consume '//' */ + /* #16 option-B: the driver emits `//ww:module-reset` + * before a package-less file's bytes; recognize the + * whole-line directive (without consuming differently) + * and flag it so lexnext emits TK_MODRESET. The body is + * then skipped like any comment. Mirrors the removed + * `// MODULE:` lexer directive. */ + { + static const char dir[] = "ww:module-reset"; + size_t i = 0; + while (dir[i] && lpeek(l, i) == dir[i]) + i++; + if (dir[i] == '\0') { + int nx = lpeek(l, i); + if (nx == '\n' || nx < 0) + l->modreset = 1; + } + } while ((c = lpeek(l, 0)) >= 0 && c != '\n') lget(l); continue; @@ -381,12 +398,15 @@ lexrune(Lex *l, Pos start) Tok lexnext(Lex *l) { - if (!skipws(l)) { - Pos p = lpos(l); - Tok t = (Tok){ TK_EOF, p, "", 0, {0}, TK_NONE }; + int more = skipws(l); + Pos start = lpos(l); + /* A `//ww:module-reset` seen in the skipped run surfaces as its own + * token before the next real one (#16 option-B boundary reset). */ + if (l->modreset) { l->modreset = 0; EMIT(TK_MODRESET); } + if (!more) { + Tok t = (Tok){ TK_EOF, start, "", 0, {0}, TK_NONE }; return t; } - Pos start = lpos(l); int c = lpeek(l, 0); if (isidstart(c)) diff --git a/cmd/wcc/parse.c b/cmd/wcc/parse.c index 1ba9f145..64869b69 100644 --- a/cmd/wcc/parse.c +++ b/cmd/wcc/parse.c @@ -1363,6 +1363,19 @@ parsefile(Parser *p) p->curmod = name; continue; } + /* `//ww:module-reset` — bundle boundary before a package-less + * file. Reset curmod to NULL so the file's decls (and its own + * `import os;`) are attributed to the primary module (""), not + * the preceding bundled package. Codegen-neutral: NULL curmod + * keeps bare symbols. (#16 option-B; closes task #11.) + * Driver-emitted ONLY before package-less files; a hand-placed + * directive after a mid-file `package` would strip subsequent + * decls to bare — that usage is deliberate-only. */ + if (p->cur.kind == TK_MODRESET) { + advance(p); + p->curmod = NULL; + continue; + } Node *attrs = parseattrs(p); int exp = accept(p, TK_EXPORT); Node *d = NULL; diff --git a/cmd/wcc/tok.c b/cmd/wcc/tok.c index eae95e71..5f92bacc 100644 --- a/cmd/wcc/tok.c +++ b/cmd/wcc/tok.c @@ -103,6 +103,7 @@ tokname(Tkind k) case TK_UNDER: return "_"; case TK_ENUM: return "enum"; case TK_MODULE: return "package"; + case TK_MODRESET: return "//ww:module-reset"; case TK_LPAREN: return "("; case TK_RPAREN: return ")"; diff --git a/cmd/wcc/ww.h b/cmd/wcc/ww.h index fef05179..b0a89f9d 100644 --- a/cmd/wcc/ww.h +++ b/cmd/wcc/ww.h @@ -180,6 +180,10 @@ typedef enum { TK_YIELD, /* `yield expr;` — value-return from a match arm */ TK_ENUM, /* Hare-style `enum [storage] { ... }` type form */ TK_MODULE, /* `module foo;` — directory-as-module declaration */ + TK_MODRESET, /* `//ww:module-reset` — driver bundle boundary: reset + * curmod to NULL before a package-less file's bytes + * (#16 option-B; the package-less-entry attribution fix + * that replaces the withdrawn `package main` inject). */ TK_LAST /* sentinel for tables */ } Tkind; @@ -207,6 +211,9 @@ struct Lex { i32 col; Arena *a; /* token-text arena */ int errs; + int modreset; /* a `//ww:module-reset` directive was seen in + * the last skipped run; lexnext emits TK_MODRESET + * before the next real token. */ }; void lexinit(Lex*, Arena*, const char *file, const char *src, u64 len); diff --git a/cmd/ww/main.c b/cmd/ww/main.c index 553e1797..15a0b2f9 100644 --- a/cmd/ww/main.c +++ b/cmd/ww/main.c @@ -306,6 +306,19 @@ expand(FILE *out, const char *path, struct ImportSet *visited, else expand(out, ipath, visited, libdir); } + /* #16 option-B: a package-less file's decls would otherwise inherit + * the preceding bundled module's sticky curmod (parser parse.c). Emit + * a curmod-reset boundary directive so the lexer/parser attribute the + * file to the primary module ("") — fixes the self-import false-fire + * and the leaked-prefix bug, codegen-neutral (bare symbols kept; not + * `package main`, which would main-prefix them). A packaged file's own + * `package` decl already sets curmod, so it needs nothing — keeping + * the directive out of every tracked combined.ww. (Task #11.) */ + { + char pkg[128]; + if (!peek_package(path, pkg, sizeof pkg)) + fputs("//ww:module-reset\n", out); + } rewind(in); int ch; while ((ch = fgetc(in)) != EOF) fputc(ch, out); diff --git a/lib/ww/lex/lex.ww b/lib/ww/lex/lex.ww index 47c8635a..48dc59b5 100644 --- a/lib/ww/lex/lex.ww +++ b/lib/ww/lex/lex.ww @@ -56,6 +56,9 @@ type lex = struct { line: i32, col: i32, errs: i32, + // a `//ww:module-reset` directive was seen in the last skipped run; + // lexnext emits TK_MODRESET before the next real token (#16 opt-B). + modreset: i32, }; export fn lexinit(l: *lex, file: str, src: *u8, len: u64) void = { @@ -66,6 +69,7 @@ export fn lexinit(l: *lex, file: str, src: *u8, len: u64) void = { l.line = 1; l.col = 1; l.errs = 0; + l.modreset = 0; }; // srcb — byte at offset; helper that lifts the cast out of indexing. @@ -127,6 +131,26 @@ fn skipws(l: *lex) bool = { let c2: i32 = lpeek(l, 1u64); if (c2 == '/') { lget(l); lget(l); // consume '//' + // #16 opt-B: recognize the driver's curmod-reset + // boundary directive `//ww:module-reset` (whole + // line) and flag it; lexnext emits TK_MODRESET. + // The body is then skipped like any comment. + // Mirrors cstage lex.c skipws. Compare via lpeek + // (no consume) so the skip loop below is unchanged. + let dir: str = "ww:module-reset"; + let di: i32 = 0; + let matched: bool = true; + for (di < dir.len) { + if (lpeek(l, di: u64) != dir[di]: i32) { + matched = false; break; + }; + di += 1; + }; + if (matched) { + let nx: i32 = lpeek(l, dir.len: u64); + if (nx == '\n') { l.modreset = 1; } + else { if (nx < 0) { l.modreset = 1; }; }; + }; for (true) { let cx: i32 = lpeek(l, 0u64); if (cx < 0) { return false; }; @@ -629,12 +653,19 @@ export fn lexnext(l: *lex, out: *tok) void = { out.text = empty; out.tsuffix = empty; - if (!skipws(l)) { - let p: pos; curpos(l, &p); - emitsimple(&p, tkind.TK_EOF, out); + let more: bool = skipws(l); + let start: pos; curpos(l, &start); + // A `//ww:module-reset` seen in the skipped run surfaces as its own + // token before the next real one (#16 opt-B boundary reset). + if (l.modreset != 0) { + l.modreset = 0; + emitsimple(&start, tkind.TK_MODRESET, out); + return; + }; + if (!more) { + emitsimple(&start, tkind.TK_EOF, out); return; }; - let start: pos; curpos(l, &start); let c: i32 = lpeek(l, 0u64); if (c >= 0) { diff --git a/lib/ww/lex/tok.ww b/lib/ww/lex/tok.ww index 5ef72be2..b136f387 100644 --- a/lib/ww/lex/tok.ww +++ b/lib/ww/lex/tok.ww @@ -118,7 +118,10 @@ type tkind = enum i32 { TK_YIELD = 84, TK_ENUM = 85, TK_MODULE = 86, // `module foo;` — directory-as-module decl - TK_LAST = 87, + TK_MODRESET = 87, // `//ww:module-reset` driver bundle boundary: + // reset curmod to "" before a package-less file + // (#16 option-B; cstage TK_MODRESET twin) + TK_LAST = 88, }; // ---- Pos / Tok -------------------------------------------------------- @@ -240,6 +243,7 @@ export fn tokname(k: tkind) str = { case tkind.TK_UNDER: return "_"; case tkind.TK_ENUM: return "enum"; case tkind.TK_MODULE: return "package"; + case tkind.TK_MODRESET: return "//ww:module-reset"; case tkind.TK_LPAREN: return "("; case tkind.TK_RPAREN: return ")"; diff --git a/lib/ww/lex/toktest.ww b/lib/ww/lex/toktest.ww index eb901ba4..91414fe8 100644 --- a/lib/ww/lex/toktest.ww +++ b/lib/ww/lex/toktest.ww @@ -128,11 +128,12 @@ fn checkname(k: tkind, want: str) void = { signalled = 185; checkname(tkind.TK_ARROW, "->"); signalled = 186; checkname(tkind.TK_FATARROW, "=>"); - signalled = 187; checkname(tkind.TK_LAST, ""); + signalled = 187; checkname(tkind.TK_MODRESET, "//ww:module-reset"); + signalled = 188; checkname(tkind.TK_LAST, ""); // Unknown kind → the post-switch fallback. TK_LAST is the highest - // named value (87); 88 is out of band, exercising the "" tail. - signalled = 188; checkname(88: tkind, ""); + // named value (88); 89 is out of band, exercising the "" tail. + signalled = 189; checkname(89: tkind, ""); }; fn checkkw(s: str, want: tkind) void = { diff --git a/lib/ww/parse/parse.ww b/lib/ww/parse/parse.ww index 66e640bd..53e58c05 100644 --- a/lib/ww/parse/parse.ww +++ b/lib/ww/parse/parse.ww @@ -411,6 +411,22 @@ export fn parsefile(p: *parser) *node = { p.curmod = name; continue; }; + // `//ww:module-reset` — bundle boundary before a package-less + // file. Reset curmod to "" so the file's decls (and its own + // `import os;`) are attributed to the primary module, not the + // preceding bundled package. Codegen-neutral: "" curmod keeps + // bare symbols. (#16 option-B; closes task #11.) + // Driver-emitted ONLY before package-less files; a hand-placed + // directive after a mid-file `package` would strip subsequent + // decls to bare — that usage is deliberate-only. + if (p.curkind == tkind.TK_MODRESET) { + advance(p); + let empty: str; + empty.ptr = nil; + empty.len = 0; + p.curmod = empty; + continue; + }; let attrs = parseattrs(p); let exported: i32 = 0; if (p.curkind == tkind.TK_EXPORT) { exported = 1; advance(p); }; diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index 5b3acc0e..719b952e 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -6441,7 +6441,10 @@ type tkind = enum i32 { TK_YIELD = 84, TK_ENUM = 85, TK_MODULE = 86, // `module foo;` — directory-as-module decl - TK_LAST = 87, + TK_MODRESET = 87, // `//ww:module-reset` driver bundle boundary: + // reset curmod to "" before a package-less file + // (#16 option-B; cstage TK_MODRESET twin) + TK_LAST = 88, }; // ---- Pos / Tok -------------------------------------------------------- @@ -6563,6 +6566,7 @@ export fn tokname(k: tkind) str = { case tkind.TK_UNDER: return "_"; case tkind.TK_ENUM: return "enum"; case tkind.TK_MODULE: return "package"; + case tkind.TK_MODRESET: return "//ww:module-reset"; case tkind.TK_LPAREN: return "("; case tkind.TK_RPAREN: return ")"; @@ -6775,6 +6779,9 @@ type lex = struct { line: i32, col: i32, errs: i32, + // a `//ww:module-reset` directive was seen in the last skipped run; + // lexnext emits TK_MODRESET before the next real token (#16 opt-B). + modreset: i32, }; export fn lexinit(l: *lex, file: str, src: *u8, len: u64) void = { @@ -6785,6 +6792,7 @@ export fn lexinit(l: *lex, file: str, src: *u8, len: u64) void = { l.line = 1; l.col = 1; l.errs = 0; + l.modreset = 0; }; // srcb — byte at offset; helper that lifts the cast out of indexing. @@ -6846,6 +6854,26 @@ fn skipws(l: *lex) bool = { let c2: i32 = lpeek(l, 1u64); if (c2 == '/') { lget(l); lget(l); // consume '//' + // #16 opt-B: recognize the driver's curmod-reset + // boundary directive `//ww:module-reset` (whole + // line) and flag it; lexnext emits TK_MODRESET. + // The body is then skipped like any comment. + // Mirrors cstage lex.c skipws. Compare via lpeek + // (no consume) so the skip loop below is unchanged. + let dir: str = "ww:module-reset"; + let di: i32 = 0; + let matched: bool = true; + for (di < dir.len) { + if (lpeek(l, di: u64) != dir[di]: i32) { + matched = false; break; + }; + di += 1; + }; + if (matched) { + let nx: i32 = lpeek(l, dir.len: u64); + if (nx == '\n') { l.modreset = 1; } + else { if (nx < 0) { l.modreset = 1; }; }; + }; for (true) { let cx: i32 = lpeek(l, 0u64); if (cx < 0) { return false; }; @@ -7348,12 +7376,19 @@ export fn lexnext(l: *lex, out: *tok) void = { out.text = empty; out.tsuffix = empty; - if (!skipws(l)) { - let p: pos; curpos(l, &p); - emitsimple(&p, tkind.TK_EOF, out); + let more: bool = skipws(l); + let start: pos; curpos(l, &start); + // A `//ww:module-reset` seen in the skipped run surfaces as its own + // token before the next real one (#16 opt-B boundary reset). + if (l.modreset != 0) { + l.modreset = 0; + emitsimple(&start, tkind.TK_MODRESET, out); + return; + }; + if (!more) { + emitsimple(&start, tkind.TK_EOF, out); return; }; - let start: pos; curpos(l, &start); let c: i32 = lpeek(l, 0u64); if (c >= 0) { @@ -8913,6 +8948,22 @@ export fn parsefile(p: *parser) *node = { p.curmod = name; continue; }; + // `//ww:module-reset` — bundle boundary before a package-less + // file. Reset curmod to "" so the file's decls (and its own + // `import os;`) are attributed to the primary module, not the + // preceding bundled package. Codegen-neutral: "" curmod keeps + // bare symbols. (#16 option-B; closes task #11.) + // Driver-emitted ONLY before package-less files; a hand-placed + // directive after a mid-file `package` would strip subsequent + // decls to bare — that usage is deliberate-only. + if (p.curkind == tkind.TK_MODRESET) { + advance(p); + let empty: str; + empty.ptr = nil; + empty.len = 0; + p.curmod = empty; + continue; + }; let attrs = parseattrs(p); let exported: i32 = 0; if (p.curkind == tkind.TK_EXPORT) { exported = 1; advance(p); }; diff --git a/selfhost/cmd/ww/main.combined.ww b/selfhost/cmd/ww/main.combined.ww index 88e043c7..06b34791 100644 --- a/selfhost/cmd/ww/main.combined.ww +++ b/selfhost/cmd/ww/main.combined.ww @@ -3315,6 +3315,19 @@ fn expand(c: *expctx, pathcs: *u8) void = { i = j + 1u64; }; + // #16 option-B: a package-less file's decls would otherwise inherit + // the preceding bundled module's sticky curmod (parser parse.ww). Emit + // a curmod-reset boundary directive so the lexer/parser attribute the + // file to the primary module ("") — fixes the self-import false-fire + // and the leaked-prefix bug, codegen-neutral (bare symbols kept; not + // `package main`, which would main-prefix them). A packaged file's own + // `package` decl already sets curmod, so it needs nothing — keeping + // the directive out of every tracked combined.ww. (Task #11.) + if (peekpackage(pathcs) == nil) { + let d: str = "//ww:module-reset\n"; + os.writeall(c.out, d.ptr, d.len: u64); + }; + os.writeall(c.out, bufp, blen); os.writeall(c.out, "\n".ptr, 1u64); }; diff --git a/selfhost/cmd/ww/main.ww b/selfhost/cmd/ww/main.ww index c2baefe2..16ba831c 100644 --- a/selfhost/cmd/ww/main.ww +++ b/selfhost/cmd/ww/main.ww @@ -529,6 +529,19 @@ fn expand(c: *expctx, pathcs: *u8) void = { i = j + 1u64; }; + // #16 option-B: a package-less file's decls would otherwise inherit + // the preceding bundled module's sticky curmod (parser parse.ww). Emit + // a curmod-reset boundary directive so the lexer/parser attribute the + // file to the primary module ("") — fixes the self-import false-fire + // and the leaked-prefix bug, codegen-neutral (bare symbols kept; not + // `package main`, which would main-prefix them). A packaged file's own + // `package` decl already sets curmod, so it needs nothing — keeping + // the directive out of every tracked combined.ww. (Task #11.) + if (peekpackage(pathcs) == nil) { + let d: str = "//ww:module-reset\n"; + os.writeall(c.out, d.ptr, d.len: u64); + }; + os.writeall(c.out, bufp, blen); os.writeall(c.out, "\n".ptr, 1u64); }; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 579965d3..a43e77c4 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -6441,7 +6441,10 @@ type tkind = enum i32 { TK_YIELD = 84, TK_ENUM = 85, TK_MODULE = 86, // `module foo;` — directory-as-module decl - TK_LAST = 87, + TK_MODRESET = 87, // `//ww:module-reset` driver bundle boundary: + // reset curmod to "" before a package-less file + // (#16 option-B; cstage TK_MODRESET twin) + TK_LAST = 88, }; // ---- Pos / Tok -------------------------------------------------------- @@ -6563,6 +6566,7 @@ export fn tokname(k: tkind) str = { case tkind.TK_UNDER: return "_"; case tkind.TK_ENUM: return "enum"; case tkind.TK_MODULE: return "package"; + case tkind.TK_MODRESET: return "//ww:module-reset"; case tkind.TK_LPAREN: return "("; case tkind.TK_RPAREN: return ")"; @@ -6775,6 +6779,9 @@ type lex = struct { line: i32, col: i32, errs: i32, + // a `//ww:module-reset` directive was seen in the last skipped run; + // lexnext emits TK_MODRESET before the next real token (#16 opt-B). + modreset: i32, }; export fn lexinit(l: *lex, file: str, src: *u8, len: u64) void = { @@ -6785,6 +6792,7 @@ export fn lexinit(l: *lex, file: str, src: *u8, len: u64) void = { l.line = 1; l.col = 1; l.errs = 0; + l.modreset = 0; }; // srcb — byte at offset; helper that lifts the cast out of indexing. @@ -6846,6 +6854,26 @@ fn skipws(l: *lex) bool = { let c2: i32 = lpeek(l, 1u64); if (c2 == '/') { lget(l); lget(l); // consume '//' + // #16 opt-B: recognize the driver's curmod-reset + // boundary directive `//ww:module-reset` (whole + // line) and flag it; lexnext emits TK_MODRESET. + // The body is then skipped like any comment. + // Mirrors cstage lex.c skipws. Compare via lpeek + // (no consume) so the skip loop below is unchanged. + let dir: str = "ww:module-reset"; + let di: i32 = 0; + let matched: bool = true; + for (di < dir.len) { + if (lpeek(l, di: u64) != dir[di]: i32) { + matched = false; break; + }; + di += 1; + }; + if (matched) { + let nx: i32 = lpeek(l, dir.len: u64); + if (nx == '\n') { l.modreset = 1; } + else { if (nx < 0) { l.modreset = 1; }; }; + }; for (true) { let cx: i32 = lpeek(l, 0u64); if (cx < 0) { return false; }; @@ -7348,12 +7376,19 @@ export fn lexnext(l: *lex, out: *tok) void = { out.text = empty; out.tsuffix = empty; - if (!skipws(l)) { - let p: pos; curpos(l, &p); - emitsimple(&p, tkind.TK_EOF, out); + let more: bool = skipws(l); + let start: pos; curpos(l, &start); + // A `//ww:module-reset` seen in the skipped run surfaces as its own + // token before the next real one (#16 opt-B boundary reset). + if (l.modreset != 0) { + l.modreset = 0; + emitsimple(&start, tkind.TK_MODRESET, out); + return; + }; + if (!more) { + emitsimple(&start, tkind.TK_EOF, out); return; }; - let start: pos; curpos(l, &start); let c: i32 = lpeek(l, 0u64); if (c >= 0) { @@ -8913,6 +8948,22 @@ export fn parsefile(p: *parser) *node = { p.curmod = name; continue; }; + // `//ww:module-reset` — bundle boundary before a package-less + // file. Reset curmod to "" so the file's decls (and its own + // `import os;`) are attributed to the primary module, not the + // preceding bundled package. Codegen-neutral: "" curmod keeps + // bare symbols. (#16 option-B; closes task #11.) + // Driver-emitted ONLY before package-less files; a hand-placed + // directive after a mid-file `package` would strip subsequent + // decls to bare — that usage is deliberate-only. + if (p.curkind == tkind.TK_MODRESET) { + advance(p); + let empty: str; + empty.ptr = nil; + empty.len = 0; + p.curmod = empty; + continue; + }; let attrs = parseattrs(p); let exported: i32 = 0; if (p.curkind == tkind.TK_EXPORT) { exported = 1; advance(p); }; diff --git a/test/wcc/737_direnum.c b/test/wcc/737_direnum.c index b6d01d97..140a0704 100644 --- a/test/wcc/737_direnum.c +++ b/test/wcc/737_direnum.c @@ -133,6 +133,46 @@ main(void) } } + /* bad-deep: same mismatch, but one file's `package` decl sits behind + * a >2048-byte comment header. Pins the PREP-peek whole-file read + * (#16): the old 2048-capped peek missed that decl, so the strict- + * same-package check skipped the file and the mismatch went + * undetected (build wrongly succeeded); the whole-file peek finds it + * → "differs from". Both stages. (reviewer-batcha pin.) */ + { + const char *src = "test/wcc/data/direnum/bad_deep_entry.ww"; + snprintf(errp, sizeof errp, "/tmp/direnum_%d_baddeep.err", getpid()); + + char cmd[2048]; + snprintf(cmd, sizeof cmd, "%s build %s 2>%s >/dev/null", + ww, src, errp); + int rc = runwait(cmd); + total++; + if (rc == 0) { + fprintf(stderr, "737[bad-deep-cstage]: expected build failure, succeeded\n"); + fail++; + } else if (!stderr_contains(errp, "differs from")) { + fprintf(stderr, "737[bad-deep-cstage]: stderr missing 'differs from'\n"); + fail++; + } + unlink(errp); + + if (access(ww_ww, X_OK) == 0) { + snprintf(cmd, sizeof cmd, "%s build %s 2>%s >/dev/null", + ww_ww, src, errp); + rc = runwait(cmd); + total++; + if (rc == 0) { + fprintf(stderr, "737[bad-deep-wwstage]: expected build failure, succeeded\n"); + fail++; + } else if (!stderr_contains(errp, "differs from")) { + fprintf(stderr, "737[bad-deep-wwstage]: stderr missing 'differs from'\n"); + fail++; + } + unlink(errp); + } + } + if (fail) { fprintf(stderr, "737_direnum: %d/%d fixtures failed\n", fail, total); return 1; diff --git a/test/wcc/data/direnum/bad_deep_entry.ww b/test/wcc/data/direnum/bad_deep_entry.ww new file mode 100644 index 00000000..b694f2ca --- /dev/null +++ b/test/wcc/data/direnum/bad_deep_entry.ww @@ -0,0 +1,5 @@ +package main; + +import bad_deep_pkg; + +export fn main() i32 = { return 0; }; diff --git a/test/wcc/data/direnum/bad_deep_pkg/a.ww b/test/wcc/data/direnum/bad_deep_pkg/a.ww new file mode 100644 index 00000000..04d6eda3 --- /dev/null +++ b/test/wcc/data/direnum/bad_deep_pkg/a.ww @@ -0,0 +1,3 @@ +package alpha; + +fn aaa() i32 = { return 1; }; diff --git a/test/wcc/data/direnum/bad_deep_pkg/b.ww b/test/wcc/data/direnum/bad_deep_pkg/b.ww new file mode 100644 index 00000000..37adb36f --- /dev/null +++ b/test/wcc/data/direnum/bad_deep_pkg/b.ww @@ -0,0 +1,54 @@ +// b.ww — #16 PREP-main peek-edge pin (reviewer-batcha). +// This file's `package beta;` decl sits behind a comment header +// longer than 2048 bytes ON PURPOSE: the old wwstage peekpackage +// capped its read at 2048 bytes and would MISS the package decl +// (return nil), so the strict-same-package dir-enum check would +// skip this file and the alpha/beta mismatch would go undetected +// (build wrongly succeeds). The PREP-peek whole-file read finds +// `package beta;`, so the mismatch fires 'differs from' and the +// build fails — which is what 737's bad_deep family asserts on +// both stages. Do not shorten this header below 2048 bytes. +// +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +// padding line to push the package decl past the 2048-byte peek window. +package beta; + +fn bbb() i32 = { return 2; };