Compile and dispatch authoritative acceptance hooks with target-specific package roots

This commit is contained in:
Timothy J. Aveni
2026-09-20 22:05:59 -07:00
parent 1e69b0e662
commit 266d2d98d0
16 changed files with 3112 additions and 2701 deletions
+40
View File
@@ -1514,6 +1514,13 @@ const lowerPackage = (
const operation = exportContext.packageOperationExport();
const generic = operation ?? exportContext.packageFunctionExport();
if (generic?.typeParameters()) {
if (generic.acceptanceClause())
loweringIssue(
state,
generic,
"unsupported-generic-acceptance",
"Acceptance hooks currently require a closed export",
);
genericExports.push(atGenericSource(generic, () => lowerGenericPackageExport(state, generic)));
return [];
}
@@ -1535,6 +1542,22 @@ const lowerPackage = (
state.types.self = previousSelf;
}
});
// Resolve after all exports have been declared, so checks can follow bodies.
for (const source of context.packageExport()) {
const declaration = source.packageOperationExport() ?? source.packageFunctionExport();
const clause = declaration?.acceptanceClause();
if (!declaration || !clause || declaration.typeParameters()) continue;
const entry = exports.find((entry) => entry.displayName === identifier(declaration.identifier()));
const check = exports.find((entry) => entry.displayName === identifier(clause.identifier()));
if (!check)
loweringIssue(
state,
clause,
"unknown-acceptance-export",
"Acceptance hook must name a closed export in this package",
);
else if (entry) entry.acceptanceExportId = check.id;
}
for (const entry of context.packageExport()) {
const specialized = entry.packageQuerySpecialization();
if (!specialized) continue;
@@ -2047,6 +2070,22 @@ const lowerConformance = (
} else if (provider.typeArguments()) {
throw new GenericTypeError("type-arity", exportName, "Non-generic export takes no type arguments");
}
const packageExport = packageSymbol?.definition?.exports.find((entry) => entry.id === exportSymbol?.exportId);
const check = packageSymbol?.definition?.exports.find((entry) => entry.id === packageExport?.acceptanceExportId);
const acceptanceBlock = provider.acceptanceBinding()?.dependencyBindingBlock();
if (acceptanceBlock && !check)
loweringIssue(
state,
acceptanceBlock,
"unexpected-acceptance-binding",
"Export does not declare an acceptance hook",
);
const acceptanceDependencies = check
? lowerBoundDependencies(state, acceptanceBlock ?? undefined, {
exportId: check.id,
ports: new Map(check.dependencyPorts.map((port) => [port.displayName, port.id])),
})
: undefined;
return packageSymbol && exportSymbol
? [
{
@@ -2056,6 +2095,7 @@ const lowerConformance = (
kind: "package" as const,
packageRevisionId: packageSymbol.revisionId,
exportId: exportSymbol.exportId,
...(acceptanceDependencies ? { acceptanceDependencies } : {}),
dependencies: lowerBoundDependencies(
state,
provider.dependencyBindingBlock() ?? undefined,