build: close package variant identity gaps
This commit is contained in:
@@ -3060,7 +3060,9 @@ lookup_visible_type(Checker *c, const char *name)
|
||||
for (Scope *p = c->cur; p; p = p->parent) {
|
||||
for (Sym *b = p->first; b; b = b->next)
|
||||
if (b->kind == SK_TYPE && strcmp(b->name, name) == 0
|
||||
&& direct_module_visible(c, b->mod))
|
||||
&& direct_module_visible(c, b->mod)
|
||||
&& (b->decl == NULL || !b->decl->imported
|
||||
|| b->decl->export))
|
||||
return b;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
@@ -1182,6 +1182,13 @@ sep_add_generated_main(struct sepgraph *g, struct sepproduct *product,
|
||||
fprintf(stderr, "ww: generated test-main identity is too long\n");
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < g->n; i++) {
|
||||
if (strcmp(g->pkg[i].path, p->path) != 0) continue;
|
||||
fprintf(stderr,
|
||||
"ww: generated test-main package identity collides with source import %s\n",
|
||||
p->path);
|
||||
return -1;
|
||||
}
|
||||
snprintf(p->entry, sizeof p->entry, "%s", variantentry);
|
||||
snprintf(p->name, sizeof p->name, "main");
|
||||
p->variant = SEP_VARIANT_TEST_MAIN;
|
||||
@@ -1361,6 +1368,21 @@ sep_topo_visit(struct sepgraph *g, int pi, int *order, int *no,
|
||||
* with an unrelated normal action in the command-global universe, but never
|
||||
* in one product. A single link closure must remain an unambiguous package
|
||||
* namespace. */
|
||||
static int
|
||||
sep_internal_replaces_production(const struct sepgraph *g, int a, int b)
|
||||
{
|
||||
const struct seppkg *internal = &g->pkg[a];
|
||||
const struct seppkg *production = &g->pkg[b];
|
||||
if (internal->variant != SEP_VARIANT_SAME_TEST) {
|
||||
internal = &g->pkg[b];
|
||||
production = &g->pkg[a];
|
||||
}
|
||||
return internal->variant == SEP_VARIANT_SAME_TEST
|
||||
&& production->variant == SEP_VARIANT_PRODUCTION
|
||||
&& production->role != SEP_ROLE_TEST_SUPPORT
|
||||
&& strcmp(internal->canon, production->canon) == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sep_validate_module_closure(struct sepgraph *g, const int *order, int n,
|
||||
int include_root)
|
||||
@@ -1372,7 +1394,8 @@ sep_validate_module_closure(struct sepgraph *g, const int *order, int n,
|
||||
for (int j = i + 1; j < n; j++) {
|
||||
int b = order[j];
|
||||
if (!include_root && g->pkg[b].root) continue;
|
||||
if (strcmp(g->pkg[a].path, g->pkg[b].path) == 0) {
|
||||
if (strcmp(g->pkg[a].path, g->pkg[b].path) == 0
|
||||
&& !sep_internal_replaces_production(g, a, b)) {
|
||||
fprintf(stderr,
|
||||
"ww: product closure contains multiple packages named %s\n",
|
||||
g->pkg[a].path);
|
||||
|
||||
@@ -312,7 +312,9 @@ fn lookupvisibletype(c: *checker, name: str) *syntax.sym = {
|
||||
for (b != nil) {
|
||||
if (b.skind == syntax.skind.SK_TYPE
|
||||
&& syntax.streq(b.name, name)
|
||||
&& directmodvisible(c, b.mod)) { return b; };
|
||||
&& directmodvisible(c, b.mod)
|
||||
&& (b.decl == nil || b.decl.imported == 0
|
||||
|| b.decl.exported != 0)) { return b; };
|
||||
b = b.snext;
|
||||
};
|
||||
p = p.parent;
|
||||
|
||||
@@ -1397,6 +1397,15 @@ fn sepaddgeneratedmain(g: *sepgraph, product: *sepproduct, ordinal: i32,
|
||||
if (variant < 0 || variant >= g.n) { return -1; };
|
||||
let p: *seppkg = &g.pkg[g.n];
|
||||
p.path = generatedmainpath(ordinal);
|
||||
let pathi: i32 = 0;
|
||||
for (pathi < g.n) {
|
||||
if (cstreq(g.pkg[pathi].path, p.path)) {
|
||||
cerr("ww: generated test-main package identity collides with source import ");
|
||||
cerr(pathstr(p.path)); cerr("\n");
|
||||
return -1;
|
||||
};
|
||||
pathi += 1;
|
||||
};
|
||||
p.entry = g.pkg[variant].entry;
|
||||
p.artifact = productartifact(ordinal, SEP_VARIANT_TEST_MAIN);
|
||||
p.name = arenadupcstr("main\0".ptr, 4u64);
|
||||
@@ -1613,6 +1622,20 @@ fn septopovisit(g: *sepgraph, pi: i32, order: []i32, no: *i32,
|
||||
return 0;
|
||||
};
|
||||
|
||||
fn sepinternalreplacesproduction(g: *sepgraph, a: i32, b: i32) bool = {
|
||||
let internal: i32 = a;
|
||||
let production: i32 = b;
|
||||
if (g.pkg[internal].variant != SEP_VARIANT_SAME_TEST) {
|
||||
internal = b;
|
||||
production = a;
|
||||
};
|
||||
return g.pkg[internal].variant == SEP_VARIANT_SAME_TEST
|
||||
&& g.pkg[production].variant == SEP_VARIANT_PRODUCTION
|
||||
&& g.pkg[production].role != SEP_ROLE_TEST_SUPPORT
|
||||
&& os.samefile(pathstr(g.pkg[internal].entry),
|
||||
pathstr(g.pkg[production].entry));
|
||||
};
|
||||
|
||||
fn sepvalidatemoduleclosure(g: *sepgraph, order: []i32, n: i32,
|
||||
includeroot: bool) i32 = {
|
||||
let i: i32 = 0;
|
||||
@@ -1624,7 +1647,8 @@ fn sepvalidatemoduleclosure(g: *sepgraph, order: []i32, n: i32,
|
||||
for (j < n) {
|
||||
let b: i32 = order[j];
|
||||
if ((includeroot || !g.pkg[b].root)
|
||||
&& cstreq(g.pkg[a].path, g.pkg[b].path)) {
|
||||
&& cstreq(g.pkg[a].path, g.pkg[b].path)
|
||||
&& !sepinternalreplacesproduction(g, a, b)) {
|
||||
cerr("ww: product closure contains multiple packages named ");
|
||||
cerr(pathstr(g.pkg[a].path)); cerr("\n");
|
||||
return -1;
|
||||
|
||||
@@ -302,7 +302,7 @@ fn m2positive(pkg: str) void = {
|
||||
};
|
||||
testenv.writefile(strings.concat(td, "/consumer.ww"), strings.concat(
|
||||
"package consumer;\nimport leaktest;\n",
|
||||
"fn forbidden(s: leaktest.secret) void = {};\n"));
|
||||
"fn forbidden(s: secret) void = {};\n"));
|
||||
let ccav: []str = [testenv.driver("w6c"), "-c", "--import",
|
||||
"leaktest", "cs.wwi", "-o", "cs.s", "consumer.ww"];
|
||||
let wcav: []str = [testenv.driver("w6c_ww"), "-c", "--import",
|
||||
@@ -314,8 +314,7 @@ fn m2positive(pkg: str) void = {
|
||||
if (cco.termination != exec.termination.EXIT || cco.code == 0
|
||||
|| wco.termination != exec.termination.EXIT || wco.code == 0
|
||||
|| !testenv.same(cco.stderr, wco.stderr)
|
||||
|| !testenv.has(cco.stderr,
|
||||
"package 'leaktest' has no exported declaration 'secret'")) {
|
||||
|| !testenv.has(cco.stderr, "unknown type 'secret'")) {
|
||||
fail("private-closure", "private nominal became source-visible");
|
||||
};
|
||||
testenv.clean(td);
|
||||
|
||||
Reference in New Issue
Block a user