ww: classify imported call returns canonically
This commit is contained in:
@@ -2492,13 +2492,20 @@ fn sretretsizetn(c: *cgen, t: *syntax.tinfo) i32 = {
|
||||
return 0;
|
||||
};
|
||||
|
||||
// callsretsize — if N_CALL `n`'s callee returns a plain TY_STRUCT
|
||||
// > 24B, return its natural size; else 0. Wraps sretretsize over the
|
||||
// callee's resolved return type, used by cglet / cgassign receive
|
||||
// sites and cgcall to detect sret at the receive / emit boundaries.
|
||||
// callsretsize — classify an N_CALL from the checker-stamped result type.
|
||||
// The callee's return AST can belong to an imported interface source whose
|
||||
// private canonical qualifier is deliberately invisible in the caller's file
|
||||
// scope. Re-resolving that spelling here loses the canonical type and can
|
||||
// select the wrong return ABI. Cstage classifies the checked Type directly;
|
||||
// sretretsizetn is its isomorphic tinfo path.
|
||||
fn callsretsize(c: *cgen, n: *syntax.node) i32 = {
|
||||
if (n == nil) { return 0; };
|
||||
if (n.kind != syntax.nkind.N_CALL) { return 0; };
|
||||
if (n.type_ != nil) {
|
||||
return sretretsizetn(c, n.type_: *syntax.tinfo);
|
||||
};
|
||||
// Raw cgen-only callers may supply an unchecked AST. Retain their
|
||||
// historical name-based fallback; production checked calls never take it.
|
||||
let callee: *syntax.node = n.lhs;
|
||||
if (callee == nil) { return 0; };
|
||||
let cn: str;
|
||||
@@ -2519,10 +2526,8 @@ fn callsretsize(c: *cgen, n: *syntax.node) i32 = {
|
||||
};
|
||||
if (cn.len == 0) { return 0; };
|
||||
let rtyp: *syntax.node = fnretlookupmod(c, cn, cmod);
|
||||
// #129: sretretsize must see the CALLEE's module context so
|
||||
// aliassamemod resolves aliases from the callee's module (not the
|
||||
// caller's). Mirrors cstage operating on resolved Type* objects
|
||||
// (type_chase_named never has this confusion). Swap + restore.
|
||||
// The unchecked fallback still needs the callee module for its
|
||||
// same-module alias preference; checked production calls bypass it above.
|
||||
let savedmod: str = c.curmod;
|
||||
if (cmod.len > 0) { c.curmod = cmod; };
|
||||
let r: i32 = sretretsize(c, rtyp);
|
||||
|
||||
@@ -224,10 +224,16 @@ fn m2positive(pkg: str) void = {
|
||||
fail("qualified", "cs.wwi != ww.wwi");
|
||||
};
|
||||
let body: str = testenv.readfile(cs);
|
||||
if (!testenv.has(body, "export fn use(x: dep.Clash) i32;")) {
|
||||
fail("qualified", ".wwi dropped the qualified signature");
|
||||
if (!testenv.has(body, "import __wwi_612e646570 a.dep;\n")
|
||||
|| !testenv.has(body,
|
||||
"export fn use(x: __wwi_612e646570.Clash) i32;")) {
|
||||
fail("qualified", ".wwi did not canonicalize the qualified signature");
|
||||
};
|
||||
if (!testenv.has(body, "//ww:module a.dep\n")
|
||||
if (testenv.has(body, "export fn use(x: dep.Clash) i32;")) {
|
||||
fail("qualified", ".wwi retained the source-file qualifier");
|
||||
};
|
||||
if (!testenv.has(body,
|
||||
"//ww:module a.dep\npackage __wwi_612e646570;\n")
|
||||
|| !testenv.has(body, "export type Clash = struct { x: i32 };")) {
|
||||
fail("qualified", ".wwi omitted the signature's origin-owned type fact");
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user