[Distributed] Move dist funcdecl getters to ASTContext

This commit is contained in:
Konrad `ktoso` Malawski
2022-01-28 10:57:39 +09:00
parent 6da455e0fa
commit e2c61d37ba
5 changed files with 95 additions and 136 deletions

View File

@@ -670,29 +670,30 @@ public:
NominalTypeDecl *actorOrSystem,
bool isVoidReturn) const;
/// Retrieve the declaration of DistributedActorSystem.make().
///
/// \param actorOrSystem distributed actor or actor system to get the
/// remoteCall function for. Since the method we're looking for is an ad-hoc
/// requirement, a specific type MUST be passed here as it is not possible
/// to obtain the decl from just the `DistributedActorSystem` protocol type.
FuncDecl *getMakeInvocationEncoderOnDistributedActorSystem(
NominalTypeDecl *actorOrSystem) const;
// Retrieve the declaration of DistributedInvocationEncoder.recordArgument(_:).
//
// \param nominal optionally provide a 'NominalTypeDecl' from which the
// function decl shall be extracted. This is useful to avoid witness calls
// through the protocol which is looked up when nominal is null.
FuncDecl *getRecordArgumentOnDistributedInvocationEncoder(
NominalTypeDecl *nominal = nullptr) const;
NominalTypeDecl *nominal) const;
// Retrieve the declaration of DistributedInvocationEncoder.recordErrorType().
//
// \param nominal optionally provide a 'NominalTypeDecl' from which the
// function decl shall be extracted. This is useful to avoid witness calls
// through the protocol which is looked up when nominal is null.
// Retrieve the declaration of DistributedInvocationEncoder.recordErrorType(_:).
FuncDecl *getRecordErrorTypeOnDistributedInvocationEncoder(
NominalTypeDecl *nominal = nullptr) const;
NominalTypeDecl *nominal) const;
// Retrieve the declaration of DistributedInvocationEncoder.recordReturnType().
//
// \param nominal optionally provide a 'NominalTypeDecl' from which the
// function decl shall be extracted. This is useful to avoid witness calls
// through the protocol which is looked up when nominal is null.
// Retrieve the declaration of DistributedInvocationEncoder.recordReturnType(_:).
FuncDecl *getRecordReturnTypeOnDistributedInvocationEncoder(
NominalTypeDecl *nominal = nullptr) const;
NominalTypeDecl *nominal) const;
// Retrieve the declaration of DistributedInvocationEncoder.doneRecording().
//
@@ -700,8 +701,7 @@ public:
// function decl shall be extracted. This is useful to avoid witness calls
// through the protocol which is looked up when nominal is null.
FuncDecl *getDoneRecordingOnDistributedInvocationEncoder(
NominalTypeDecl *nominal = nullptr) const;
NominalTypeDecl *nominal) const;
/// Look for the declaration with the given name within the
/// passed in module.

View File

@@ -3370,9 +3370,6 @@ public:
/// Find, or potentially synthesize, the implicit 'id' property of this actor.
VarDecl *getDistributedActorIDProperty() const;
/// Find the 'makeInvocation' function.
AbstractFunctionDecl* getDistributedActorSystemMakeInvocationEncoderFunction() const;
/// Find the 'RemoteCallTarget.init(_mangledName:)' initializer function
ConstructorDecl* getDistributedRemoteCallTargetInitFunction() const;

View File

@@ -267,18 +267,6 @@ struct ASTContext::Implementation {
/// -> Builtin.Int1
FuncDecl *IsOSVersionAtLeastDecl = nullptr;
/// func recordArgument(_:) throws
FuncDecl *RecordArgumentDistributedInvocationEncoderDecl = nullptr;
/// func recordErrorType(_:) throws
FuncDecl *RecordErrorTypeDistributedInvocationEncoderDecl = nullptr;
/// func recordReturnType(_:) throws
FuncDecl *RecordReturnTypeDistributedInvocationEncoderDecl = nullptr;
/// func doneRecording() throws
FuncDecl *DoneRecordingDistributedInvocationEncoderDecl = nullptr;
/// The set of known protocols, lazily populated as needed.
ProtocolDecl *KnownProtocols[NumKnownProtocols] = { };
@@ -1295,7 +1283,7 @@ AbstractFunctionDecl *ASTContext::getRemoteCallOnDistributedActorSystem(
NominalTypeDecl *actorOrSystem, bool isVoidReturn) const {
assert(actorOrSystem && "distributed actor (or system) decl must be provided");
const NominalTypeDecl *system = actorOrSystem;
if (actorOrSystem && actorOrSystem->isDistributedActor()) {
if (actorOrSystem->isDistributedActor()) {
auto var = actorOrSystem->getDistributedActorSystemProperty();
system = var->getInterfaceType()->getAnyNominal();
}
@@ -1310,32 +1298,49 @@ AbstractFunctionDecl *ASTContext::getRemoteCallOnDistributedActorSystem(
nullptr);
}
FuncDecl *ASTContext::getRecordArgumentOnDistributedInvocationEncoder(
NominalTypeDecl *nominal) const {
if (getImpl().RecordArgumentDistributedInvocationEncoderDecl) {
return getImpl().RecordArgumentDistributedInvocationEncoderDecl;
FuncDecl *ASTContext::getMakeInvocationEncoderOnDistributedActorSystem(
NominalTypeDecl *actorOrSystem) const {
NominalTypeDecl *system = actorOrSystem;
assert(actorOrSystem && "distributed actor (or system) decl must be provided");
if (actorOrSystem->isDistributedActor()) {
auto var = actorOrSystem->getDistributedActorSystemProperty();
system = var->getInterfaceType()->getAnyNominal();
}
NominalTypeDecl *encoderProto = nominal ?
nominal :
getProtocol(KnownProtocolKind::DistributedTargetInvocationEncoder);
assert(encoderProto && "Missing DistributedTargetInvocationEncoder protocol");
for (auto result : encoderProto->lookupDirect(Id_recordArgument)) {
for (auto result : system->lookupDirect(Id_makeInvocationEncoder)) {
auto *fd = dyn_cast<FuncDecl>(result);
if (!fd)
continue;
if (fd->getParameters()->size() != 0)
continue;
if (fd->hasAsync())
continue;
if (fd->hasThrows())
continue;
// TODO(distributed): more checks, return type etc
return fd;
}
return nullptr;
}
FuncDecl *ASTContext::getRecordArgumentOnDistributedInvocationEncoder(
NominalTypeDecl *nominal) const {
for (auto result : nominal->lookupDirect(Id_recordArgument)) {
auto *fd = dyn_cast<FuncDecl>(result);
if (!fd)
continue;
if (fd->getParameters()->size() != 1)
continue;
if (fd->hasAsync())
continue;
if (!fd->hasThrows())
continue;
// TODO(distributed): more checks
if (fd->getResultInterfaceType()->isVoid() &&
fd->hasThrows() &&
!fd->hasAsync()) {
getImpl().RecordArgumentDistributedInvocationEncoderDecl = fd;
if (fd->getResultInterfaceType()->isVoid())
return fd;
}
}
return nullptr;
@@ -1343,31 +1348,20 @@ FuncDecl *ASTContext::getRecordArgumentOnDistributedInvocationEncoder(
FuncDecl *ASTContext::getRecordErrorTypeOnDistributedInvocationEncoder(
NominalTypeDecl *nominal) const {
if (getImpl().RecordErrorTypeDistributedInvocationEncoderDecl) {
return getImpl().RecordErrorTypeDistributedInvocationEncoderDecl;
}
NominalTypeDecl *encoderProto =
nominal
? nominal
: getProtocol(KnownProtocolKind::DistributedTargetInvocationEncoder);
assert(encoderProto && "Missing DistributedTargetInvocationEncoder protocol");
for (auto result : encoderProto->lookupDirect(Id_recordErrorType)) {
for (auto result : nominal->lookupDirect(Id_recordErrorType)) {
auto *fd = dyn_cast<FuncDecl>(result);
if (!fd)
continue;
if (fd->getParameters()->size() != 1)
continue;
if (fd->hasAsync())
continue;
if (!fd->hasThrows())
continue;
// TODO(distributed): more checks
// TODO(distributed): more checks that the arg type matches (!!!)
if (fd->getResultInterfaceType()->isVoid() &&
fd->hasThrows() &&
!fd->hasAsync()) {
getImpl().RecordErrorTypeDistributedInvocationEncoderDecl = fd;
if (fd->getResultInterfaceType()->isVoid())
return fd;
}
}
return nullptr;
@@ -1375,31 +1369,20 @@ FuncDecl *ASTContext::getRecordErrorTypeOnDistributedInvocationEncoder(
FuncDecl *ASTContext::getRecordReturnTypeOnDistributedInvocationEncoder(
NominalTypeDecl *nominal) const {
if (getImpl().RecordReturnTypeDistributedInvocationEncoderDecl) {
return getImpl().RecordReturnTypeDistributedInvocationEncoderDecl;
}
NominalTypeDecl *encoderProto =
nominal
? nominal
: getProtocol(KnownProtocolKind::DistributedTargetInvocationEncoder);
assert(encoderProto && "Missing DistributedTargetInvocationEncoder protocol");
for (auto result : encoderProto->lookupDirect(Id_recordReturnType)) {
for (auto result : nominal->lookupDirect(Id_recordReturnType)) {
auto *fd = dyn_cast<FuncDecl>(result);
if (!fd)
continue;
if (fd->getParameters()->size() != 1)
continue;
if (fd->hasAsync())
continue;
if (!fd->hasThrows())
continue;
// TODO(distributed): more checks
// TODO(distributed): more checks that the arg type matches (!!!)
if (fd->getResultInterfaceType()->isVoid() &&
fd->hasThrows() &&
!fd->hasAsync()) {
getImpl().RecordReturnTypeDistributedInvocationEncoderDecl = fd;
if (fd->getResultInterfaceType()->isVoid())
return fd;
}
}
return nullptr;
@@ -1407,16 +1390,7 @@ FuncDecl *ASTContext::getRecordReturnTypeOnDistributedInvocationEncoder(
FuncDecl *ASTContext::getDoneRecordingOnDistributedInvocationEncoder(
NominalTypeDecl *nominal) const {
if (getImpl().DoneRecordingDistributedInvocationEncoderDecl) {
return getImpl().DoneRecordingDistributedInvocationEncoderDecl;
}
NominalTypeDecl *encoderProto =
nominal
? nominal
: getProtocol(KnownProtocolKind::DistributedTargetInvocationEncoder);
assert(encoderProto && "Missing DistributedTargetInvocationEncoder protocol");
for (auto result : encoderProto->lookupDirect(Id_doneRecording)) {
for (auto result : nominal->lookupDirect(Id_doneRecording)) {
auto *fd = dyn_cast<FuncDecl>(result);
if (!fd)
continue;
@@ -1426,10 +1400,8 @@ FuncDecl *ASTContext::getDoneRecordingOnDistributedInvocationEncoder(
if (fd->getResultInterfaceType()->isVoid() &&
fd->hasThrows() &&
!fd->hasAsync()) {
getImpl().DoneRecordingDistributedInvocationEncoderDecl = fd;
!fd->hasAsync())
return fd;
}
}
return nullptr;

View File

@@ -7402,17 +7402,14 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
auto callId = isVoidReturn ? C.Id_remoteCallVoid : C.Id_remoteCall;
// Check the name
if (this->getBaseName() != callId)
if (getBaseName() != callId)
return false;
auto params = this->getParameters();
auto params = getParameters();
unsigned int expectedParamNum = isVoidReturn ? 4 : 5;
// Check the expected argument count
// - for value returning remoteCall:
if (!params || (!isVoidReturn && params->size() != 5))
return false;
// - for void returning remoteCallVoid:
if (!params || (isVoidReturn && params->size() != 4))
// Check the expected argument count:
if (!params || params->size() != expectedParamNum)
return false;
// Check API names of the arguments
@@ -7422,7 +7419,7 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
auto thrownTypeParam = params->get(3);
if (actorParam->getArgumentName() != C.Id_on ||
targetParam->getArgumentName() != C.Id_target ||
invocationParam->getArgumentName() != C.Id_invocationDecoder ||
invocationParam->getArgumentName() != C.Id_invocation ||
thrownTypeParam->getArgumentName() != C.Id_throwing)
return false;
@@ -7432,6 +7429,26 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
return false;
}
if (!isGeneric())
return false;
auto genericParams = getGenericParams();
unsigned int expectedGenericParamNum = isVoidReturn ? 2 : 3;
// We expect: Act, Err, Res?
if (genericParams->size() != expectedGenericParamNum) {
return false;
}
// FIXME(distributed): check the exact generic requirements
// === check the return type
if (isVoidReturn) {
if (auto func = dyn_cast<FuncDecl>(this))
if (!func->getResultInterfaceType()->isVoid())
return false;
}
// FIXME(distributed): check the right types of the args and generics...
// FIXME(distributed): check access level actually is ok, i.e. not private etc
@@ -7439,34 +7456,7 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
}
bool AbstractFunctionDecl::isDistributed() const {
return this->getAttrs().hasAttribute<DistributedActorAttr>();
}
AbstractFunctionDecl*
NominalTypeDecl::getDistributedActorSystemMakeInvocationEncoderFunction() const {
auto &C = this->getASTContext();
NominalTypeDecl *system = const_cast<NominalTypeDecl *>(this);
if (this->isDistributedActor()) {
auto var = this->getDistributedActorSystemProperty();
system = var->getInterfaceType()->getAnyNominal();
}
// FIXME(distributed): implement more properly...
for (auto value : system->lookupDirect(C.Id_makeInvocationEncoder)) {
auto func = dyn_cast<AbstractFunctionDecl>(value);
if (!func)
continue;
if (func->getParameters()->size() != 0)
continue;
// TODO(distriuted): return type must conform to our expected protocol
return func;
}
// TODO(distributed): make a Request for it?
return nullptr;
return getAttrs().hasAttribute<DistributedActorAttr>();
}
ConstructorDecl*

View File

@@ -724,8 +724,8 @@ void SILGenFunction::emitDistributedThunk(SILDeclRef thunk) {
// === `InvocationEncoder` types
AbstractFunctionDecl *makeInvocationEncoderFnDecl =
selfTyDecl->getDistributedActorSystemMakeInvocationEncoderFunction();
assert(makeInvocationEncoderFnDecl && "no remoteCall func found!");
ctx.getMakeInvocationEncoderOnDistributedActorSystem(selfTyDecl);
assert(makeInvocationEncoderFnDecl && "no 'makeInvocationEncoder' func found!");
auto makeInvocationEncoderFnRef = SILDeclRef(makeInvocationEncoderFnDecl);
ProtocolDecl *invocationEncoderProto =
@@ -882,7 +882,7 @@ void SILGenFunction::emitDistributedThunk(SILDeclRef thunk) {
// function_ref FakeActorSystem.makeInvocationEncoder()
// %19 = function_ref @$s27FakeDistributedActorSystems0aC6SystemV21makeInvocationEncoderAA0aG0VyF : $@convention(method) (@guaranteed FakeActorSystem) -> FakeInvocation // user: %20
auto makeInvocationEncoderFnSIL =
SILFunction *makeInvocationEncoderFnSIL =
builder.getOrCreateFunction(loc, makeInvocationEncoderFnRef, NotForDefinition);
SILValue makeInvocationEncoderFn =
B.createFunctionRefFor(loc, makeInvocationEncoderFnSIL);
@@ -1395,7 +1395,7 @@ void SILGenFunction::emitDistributedThunk(SILDeclRef thunk) {
}
assert(returnMetatypeValue);
// function_ref FakeActorSystem.remoteCall<A, B, C>(on:target:invocationDecoder:throwing:returning:)
// function_ref FakeActorSystem.remoteCall<A, B, C>(on:target:invocation:throwing:returning:)
// %49 = function_ref @$s27FakeDistributedActorSystems0aC6SystemV10remoteCall2on6target17invocationDecoder8throwing9returningq0_x_01_B006RemoteG6TargetVAA0A10InvocationVzq_mq0_mSgtYaKAJ0bC0RzSeR0_SER0_AA0C7AddressV2IDRtzr1_lF : $@convention(method) @async <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : DistributedActor, τ_0_2 : Decodable, τ_0_2 : Encodable, τ_0_0.ID == ActorAddress> (@guaranteed τ_0_0, @in_guaranteed RemoteCallTarget, @inout FakeInvocation, @thick τ_0_1.Type, Optional<@thick τ_0_2.Type>, @guaranteed FakeActorSystem) -> (@out τ_0_2, @error Error) // user: %50
auto remoteCallFnDecl =
ctx.getRemoteCallOnDistributedActorSystem(selfTyDecl, /*isVoid=*/resultType.isVoid());