mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[stdlib] Distributed: Remove invokeOnReturn requirement and its synthesis
This is no longer necessary because `onReturn` is a protocol requirement now.
This commit is contained in:
@@ -121,319 +121,6 @@ static FuncDecl *deriveDistributedActor_resolve(DerivedConformance &derived) {
|
||||
return factoryDecl;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*************** INVOKE HANDLER ON-RETURN FUNCTION ****************************/
|
||||
/******************************************************************************/
|
||||
|
||||
namespace {
|
||||
struct DoInvokeOnReturnContext {
|
||||
ParamDecl *handlerParam;
|
||||
ParamDecl *resultBufferParam;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static std::pair<BraceStmt *, bool>
|
||||
deriveBodyDistributed_doInvokeOnReturn(AbstractFunctionDecl *afd, void *arg) {
|
||||
auto &C = afd->getASTContext();
|
||||
auto *context = static_cast<DoInvokeOnReturnContext *>(arg);
|
||||
|
||||
// mock locations, we're a thunk and don't really need detailed locations
|
||||
const SourceLoc sloc = SourceLoc();
|
||||
const DeclNameLoc dloc = DeclNameLoc();
|
||||
bool implicit = true;
|
||||
|
||||
auto returnTypeParam = afd->getParameters()->get(0);
|
||||
SmallVector<ASTNode, 8> stmts;
|
||||
|
||||
VarDecl *resultVar =
|
||||
new (C) VarDecl(/*isStatic=*/false, VarDecl::Introducer::Let, sloc,
|
||||
C.getIdentifier("result"), afd);
|
||||
{
|
||||
auto resultLoadCall = CallExpr::createImplicit(
|
||||
C,
|
||||
UnresolvedDotExpr::createImplicit(
|
||||
C,
|
||||
/*base=*/
|
||||
new (C) DeclRefExpr(ConcreteDeclRef(context->resultBufferParam),
|
||||
dloc, implicit),
|
||||
/*baseName=*/DeclBaseName(C.getIdentifier("load")),
|
||||
/*argLabels=*/
|
||||
{C.getIdentifier("fromByteOffset"), C.getIdentifier("as")}),
|
||||
ArgumentList::createImplicit(
|
||||
C, {Argument(sloc, C.getIdentifier("as"),
|
||||
new (C) DeclRefExpr(ConcreteDeclRef(returnTypeParam),
|
||||
dloc, implicit))}));
|
||||
|
||||
auto resultPattern = NamedPattern::createImplicit(C, resultVar);
|
||||
auto resultPB = PatternBindingDecl::createImplicit(
|
||||
C, swift::StaticSpellingKind::None, resultPattern,
|
||||
/*expr=*/resultLoadCall, afd);
|
||||
|
||||
stmts.push_back(resultPB);
|
||||
stmts.push_back(resultVar);
|
||||
}
|
||||
|
||||
// call the ad-hoc `handler.onReturn`
|
||||
{
|
||||
// Find the ad-hoc requirement ensured function on the concrete handler:
|
||||
auto onReturnFunc = C.getOnReturnOnDistributedTargetInvocationResultHandler(
|
||||
context->handlerParam->getInterfaceType()->getAnyNominal());
|
||||
assert(onReturnFunc && "did not find ad-hoc requirement witness!");
|
||||
|
||||
Expr *callExpr = CallExpr::createImplicit(
|
||||
C,
|
||||
UnresolvedDotExpr::createImplicit(
|
||||
C,
|
||||
/*base=*/
|
||||
new (C) DeclRefExpr(ConcreteDeclRef(context->handlerParam), dloc,
|
||||
implicit),
|
||||
/*baseName=*/onReturnFunc->getBaseName(),
|
||||
/*paramList=*/onReturnFunc->getParameters()),
|
||||
ArgumentList::forImplicitCallTo(
|
||||
DeclNameRef(onReturnFunc->getName()),
|
||||
{new (C) DeclRefExpr(ConcreteDeclRef(resultVar), dloc, implicit)},
|
||||
C));
|
||||
callExpr = TryExpr::createImplicit(C, sloc, callExpr);
|
||||
callExpr = AwaitExpr::createImplicit(C, sloc, callExpr);
|
||||
|
||||
stmts.push_back(callExpr);
|
||||
}
|
||||
|
||||
auto body = BraceStmt::create(C, sloc, {stmts}, sloc, implicit);
|
||||
return {body, /*isTypeChecked=*/false};
|
||||
}
|
||||
|
||||
// Create local function:
|
||||
// func invokeOnReturn<R: Self.SerializationRequirement>(
|
||||
// _ returnType: R.Type
|
||||
// ) async throws {
|
||||
// let value = resultBuffer.load(as: returnType)
|
||||
// try await handler.onReturn(value: value)
|
||||
// }
|
||||
static FuncDecl* createLocalFunc_doInvokeOnReturn(
|
||||
ASTContext& C, FuncDecl* parentFunc,
|
||||
NominalTypeDecl* systemNominal,
|
||||
ParamDecl* handlerParam,
|
||||
ParamDecl* resultBufParam) {
|
||||
auto DC = parentFunc;
|
||||
auto DAS = C.getDistributedActorSystemDecl();
|
||||
auto doInvokeLocalFuncIdent = C.getIdentifier("doInvokeOnReturn");
|
||||
|
||||
// mock locations, we're a synthesized func and don't need real locations
|
||||
const SourceLoc sloc = SourceLoc();
|
||||
|
||||
// <R: Self.SerializationRequirement>
|
||||
// We create the generic param at invalid depth, which means it'll be filled
|
||||
// by semantic analysis.
|
||||
auto *resultGenericParamDecl = GenericTypeParamDecl::createImplicit(
|
||||
parentFunc, C.getIdentifier("R"), /*depth*/ 0, /*index*/ 0);
|
||||
GenericParamList *doInvokeGenericParamList =
|
||||
GenericParamList::create(C, sloc, {resultGenericParamDecl}, sloc);
|
||||
|
||||
auto returnTypeIdent = C.getIdentifier("returnType");
|
||||
auto resultTyParamDecl =
|
||||
ParamDecl::createImplicit(C,
|
||||
/*argument=*/returnTypeIdent,
|
||||
/*parameter=*/returnTypeIdent,
|
||||
resultGenericParamDecl->getInterfaceType(), DC);
|
||||
ParameterList *doInvokeParamsList =
|
||||
ParameterList::create(C, {resultTyParamDecl});
|
||||
|
||||
SmallVector<Requirement, 2> requirements;
|
||||
for (auto p : getDistributedSerializationRequirementProtocols(systemNominal, DAS)) {
|
||||
auto requirement =
|
||||
Requirement(RequirementKind::Conformance,
|
||||
resultGenericParamDecl->getDeclaredInterfaceType(),
|
||||
p->getDeclaredInterfaceType());
|
||||
requirements.push_back(requirement);
|
||||
}
|
||||
GenericSignature doInvokeGenSig =
|
||||
buildGenericSignature(C, parentFunc->getGenericSignature(),
|
||||
{resultGenericParamDecl->getDeclaredInterfaceType()
|
||||
->castTo<GenericTypeParamType>()},
|
||||
std::move(requirements),
|
||||
/*allowInverses=*/true);
|
||||
|
||||
FuncDecl *doInvokeOnReturnFunc = FuncDecl::createImplicit(
|
||||
C, swift::StaticSpellingKind::None,
|
||||
DeclName(C, doInvokeLocalFuncIdent, doInvokeParamsList),
|
||||
sloc,
|
||||
/*async=*/true,
|
||||
/*throws=*/true,
|
||||
/*ThrownType=*/Type(),
|
||||
doInvokeGenericParamList, doInvokeParamsList,
|
||||
/*returnType=*/C.TheEmptyTupleType, parentFunc);
|
||||
doInvokeOnReturnFunc->setImplicit();
|
||||
doInvokeOnReturnFunc->setSynthesized();
|
||||
doInvokeOnReturnFunc->setGenericSignature(doInvokeGenSig);
|
||||
|
||||
auto *doInvokeContext = C.Allocate<DoInvokeOnReturnContext>();
|
||||
doInvokeContext->handlerParam = handlerParam;
|
||||
doInvokeContext->resultBufferParam = resultBufParam;
|
||||
doInvokeOnReturnFunc->setBodySynthesizer(
|
||||
deriveBodyDistributed_doInvokeOnReturn, doInvokeContext);
|
||||
|
||||
return doInvokeOnReturnFunc;
|
||||
}
|
||||
|
||||
static std::pair<BraceStmt *, bool>
|
||||
deriveBodyDistributed_invokeHandlerOnReturn(AbstractFunctionDecl *afd,
|
||||
void *context) {
|
||||
auto implicit = true;
|
||||
ASTContext &C = afd->getASTContext();
|
||||
auto DC = afd->getDeclContext();
|
||||
auto DAS = C.getDistributedActorSystemDecl();
|
||||
|
||||
// mock locations, we're a thunk and don't really need detailed locations
|
||||
const SourceLoc sloc = SourceLoc();
|
||||
const DeclNameLoc dloc = DeclNameLoc();
|
||||
|
||||
NominalTypeDecl *nominal = dyn_cast<NominalTypeDecl>(DC);
|
||||
assert(nominal);
|
||||
|
||||
auto func = dyn_cast<FuncDecl>(afd);
|
||||
assert(func);
|
||||
|
||||
// === parameters
|
||||
auto params = func->getParameters();
|
||||
assert(params->size() == 3);
|
||||
auto handlerParam = params->get(0);
|
||||
auto resultBufParam = params->get(1);
|
||||
auto metatypeParam = params->get(2);
|
||||
|
||||
auto serializationRequirementTypeTy =
|
||||
getDistributedSerializationRequirementType(nominal, DAS);
|
||||
|
||||
auto serializationRequirementMetaTypeTy =
|
||||
ExistentialMetatypeType::get(serializationRequirementTypeTy);
|
||||
|
||||
// Statements
|
||||
SmallVector<ASTNode, 8> stmts;
|
||||
|
||||
// --- `let m = metatype as! SerializationRequirement.Type`
|
||||
VarDecl *metatypeVar =
|
||||
new (C) VarDecl(/*isStatic=*/false, VarDecl::Introducer::Let, sloc,
|
||||
C.getIdentifier("m"), func);
|
||||
{
|
||||
metatypeVar->setImplicit();
|
||||
metatypeVar->setSynthesized();
|
||||
|
||||
// metatype as! <<concrete SerializationRequirement.Type>>
|
||||
auto metatypeRef =
|
||||
new (C) DeclRefExpr(ConcreteDeclRef(metatypeParam), dloc, implicit);
|
||||
auto metatypeSRCastExpr = ForcedCheckedCastExpr::createImplicit(
|
||||
C, metatypeRef, serializationRequirementMetaTypeTy);
|
||||
|
||||
auto metatypePattern = NamedPattern::createImplicit(C, metatypeVar);
|
||||
auto metatypePB = PatternBindingDecl::createImplicit(
|
||||
C, swift::StaticSpellingKind::None, metatypePattern,
|
||||
/*expr=*/metatypeSRCastExpr, func);
|
||||
|
||||
stmts.push_back(metatypePB);
|
||||
stmts.push_back(metatypeVar);
|
||||
}
|
||||
|
||||
// --- Declare the local function `doInvokeOnReturn`...
|
||||
FuncDecl *doInvokeOnReturnFunc = createLocalFunc_doInvokeOnReturn(
|
||||
C, func,
|
||||
nominal, handlerParam, resultBufParam);
|
||||
stmts.push_back(doInvokeOnReturnFunc);
|
||||
|
||||
// --- try await _openExistential(metatypeVar, do: <<doInvokeLocalFunc>>)
|
||||
{
|
||||
auto openExistentialBaseIdent = C.getIdentifier("_openExistential");
|
||||
auto doIdent = C.getIdentifier("do");
|
||||
|
||||
auto openExArgs = ArgumentList::createImplicit(
|
||||
C, {
|
||||
Argument(sloc, Identifier(),
|
||||
new (C) DeclRefExpr(ConcreteDeclRef(metatypeVar), dloc,
|
||||
implicit)),
|
||||
Argument(sloc, doIdent,
|
||||
new (C) DeclRefExpr(ConcreteDeclRef(doInvokeOnReturnFunc),
|
||||
dloc, implicit)),
|
||||
});
|
||||
Expr *tryAwaitDoOpenExistential =
|
||||
CallExpr::createImplicit(C,
|
||||
UnresolvedDeclRefExpr::createImplicit(
|
||||
C, openExistentialBaseIdent),
|
||||
openExArgs);
|
||||
|
||||
tryAwaitDoOpenExistential =
|
||||
AwaitExpr::createImplicit(C, sloc, tryAwaitDoOpenExistential);
|
||||
tryAwaitDoOpenExistential =
|
||||
TryExpr::createImplicit(C, sloc, tryAwaitDoOpenExistential);
|
||||
|
||||
stmts.push_back(tryAwaitDoOpenExistential);
|
||||
}
|
||||
|
||||
auto body = BraceStmt::create(C, sloc, {stmts}, sloc, implicit);
|
||||
return {body, /*isTypeChecked=*/false};
|
||||
}
|
||||
|
||||
/// Synthesizes the
|
||||
///
|
||||
/// \verbatim
|
||||
/// static func invokeHandlerOnReturn(
|
||||
//// handler: ResultHandler,
|
||||
//// resultBuffer: UnsafeRawPointer,
|
||||
//// metatype _metatype: Any.Type
|
||||
//// ) async throws
|
||||
/// \endverbatim
|
||||
static FuncDecl *deriveDistributedActorSystem_invokeHandlerOnReturn(
|
||||
DerivedConformance &derived) {
|
||||
auto system = derived.Nominal;
|
||||
auto &C = system->getASTContext();
|
||||
|
||||
// auto serializationRequirementType = getDistributedActorSystemType(decl);
|
||||
auto resultHandlerType = getDistributedActorSystemResultHandlerType(system);
|
||||
auto unsafeRawPointerType = C.getUnsafeRawPointerType();
|
||||
auto anyTypeType = ExistentialMetatypeType::get(C.TheAnyType); // Any.Type
|
||||
|
||||
// auto serializationRequirementType =
|
||||
// getDistributedSerializationRequirementType(system, DAS);
|
||||
|
||||
// params:
|
||||
// - handler: Self.ResultHandler
|
||||
// - resultBuffer:
|
||||
// - metatype _metatype: Any.Type
|
||||
auto *params = ParameterList::create(
|
||||
C,
|
||||
/*LParenLoc=*/SourceLoc(),
|
||||
/*params=*/
|
||||
{
|
||||
ParamDecl::createImplicit(
|
||||
C, C.Id_handler, C.Id_handler,
|
||||
system->mapTypeIntoContext(resultHandlerType), system),
|
||||
ParamDecl::createImplicit(
|
||||
C, C.Id_resultBuffer, C.Id_resultBuffer,
|
||||
unsafeRawPointerType, system),
|
||||
ParamDecl::createImplicit(
|
||||
C, C.Id_metatype, C.Id_metatype,
|
||||
anyTypeType, system)
|
||||
},
|
||||
/*RParenLoc=*/SourceLoc());
|
||||
|
||||
// Func name: invokeHandlerOnReturn(handler:resultBuffer:metatype)
|
||||
DeclName name(C, C.Id_invokeHandlerOnReturn, params);
|
||||
|
||||
// Expected type: (Self.ResultHandler, UnsafeRawPointer, any Any.Type) async
|
||||
// throws -> ()
|
||||
auto *funcDecl =
|
||||
FuncDecl::createImplicit(C, StaticSpellingKind::None, name, SourceLoc(),
|
||||
/*async=*/true,
|
||||
/*throws=*/true,
|
||||
/*ThrownType=*/Type(),
|
||||
/*genericParams=*/nullptr, params,
|
||||
/*returnType*/ TupleType::getEmpty(C), system);
|
||||
funcDecl->setSynthesized(true);
|
||||
funcDecl->copyFormalAccessFrom(system, /*sourceIsParentContext=*/true);
|
||||
funcDecl->setBodySynthesizer(deriveBodyDistributed_invokeHandlerOnReturn);
|
||||
|
||||
derived.addMembersToConformanceContext({funcDecl});
|
||||
return funcDecl;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************* PROPERTIES ***********************************/
|
||||
/******************************************************************************/
|
||||
@@ -936,14 +623,6 @@ std::pair<Type, TypeDecl *> DerivedConformance::deriveDistributedActor(
|
||||
|
||||
ValueDecl *
|
||||
DerivedConformance::deriveDistributedActorSystem(ValueDecl *requirement) {
|
||||
if (auto func = dyn_cast<FuncDecl>(requirement)) {
|
||||
// just a simple name check is enough here,
|
||||
// if we are invoked here we know for sure it is for the "right" function
|
||||
if (func->getName().getBaseName() == Context.Id_invokeHandlerOnReturn) {
|
||||
return deriveDistributedActorSystem_invokeHandlerOnReturn(*this);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user