Skip to content

[WIP] DistributedActors and distributed funcs in protocols must survive hop_to them #41451

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
9 changes: 4 additions & 5 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -658,12 +658,11 @@ class ASTContext final {

/// 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.
/// \param thunk the function from which we'll be invoking things on the obtained
/// actor system; This way we'll always get the right type, taking care of any
/// where clauses etc.
FuncDecl *getMakeInvocationEncoderOnDistributedActorSystem(
NominalTypeDecl *actorOrSystem) const;
AbstractFunctionDecl *thunk) const;

// Retrieve the declaration of
// DistributedInvocationEncoder.recordGenericSubstitution(_:).
Expand Down
4 changes: 0 additions & 4 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4472,10 +4472,6 @@ class ProtocolDecl final : public NominalTypeDecl {
/// semantics but has no corresponding witness table.
bool isMarkerProtocol() const;

/// Is a protocol that can only be conformed by distributed actors.
/// Such protocols are allowed to contain distributed functions.
bool inheritsFromDistributedActor() const;

private:
void computeKnownProtocolKind() const;

Expand Down
7 changes: 6 additions & 1 deletion include/swift/AST/DistributedDecl.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ class DeclContext;
class FuncDecl;
class NominalTypeDecl;

/// Determine the concrete type of 'ActorSystem' as seen from the member.
/// E.g. when in a protocol, and trying to determine what the actor system was
/// constrained to.
Type getConcreteReplacementForProtocolActorSystemType(ValueDecl *member);

/// Determine the `ActorSystem` type for the given actor.
Type getDistributedActorSystemType(NominalTypeDecl *actor);
Type getDistributedActorSystemType(ClassDecl *actor);

/// Determine the `ID` type for the given actor.
Type getDistributedActorIDType(NominalTypeDecl *actor);
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/KnownSDKTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ KNOWN_SDK_TYPE_DECL(Concurrency, TaskLocal, ClassDecl, 1)

// Distributed actors
KNOWN_SDK_TYPE_DECL(Distributed, DistributedActor, ProtocolDecl, 0)
KNOWN_SDK_TYPE_DECL(Distributed, DistributedActorSystem, ProtocolDecl, 0)
KNOWN_SDK_TYPE_DECL(Distributed, RemoteCallTarget, StructDecl, 0)

// String processing
Expand Down
4 changes: 4 additions & 0 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,10 @@ class alignas(1 << TypeAlignInBits) TypeBase
/// Determines whether this type is an actor type.
bool isActorType();

/// Determines whether this type conforms or inherits (if it's a protocol
/// type) from `DistributedActor`.
bool isDistributedActor();

/// Determines the element type of a known
/// [Autoreleasing]Unsafe[Mutable][Raw]Pointer variant, or returns null if the
/// type is not a pointer.
Expand Down
1 change: 1 addition & 0 deletions include/swift/SIL/SILDeclRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ struct SILDeclRef {
/// entry point of a class ConstructorDecl or the constructor of a value
/// ConstructorDecl.
Allocator,

/// Initializer - this constant references the initializing constructor
/// entry point of the class ConstructorDecl in loc.
Initializer,
Expand Down
12 changes: 6 additions & 6 deletions include/swift/SIL/SILModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ class SILModule {
/// Action to be executed for serializing the SILModule.
ActionCallback SerializeSILAction;

#if NDEBUG
#ifndef NDEBUG
BasicBlockNameMapType basicBlockNames;
#endif

Expand Down Expand Up @@ -456,20 +456,20 @@ class SILModule {
bool isSerialized() const { return serialized; }

void setBasicBlockName(const SILBasicBlock *block, StringRef name) {
#if NDEBUG
#ifndef NDEBUG
basicBlockNames[block] = name.str();
#endif
#endif
}
Optional<StringRef> getBasicBlockName(const SILBasicBlock *block) {
#if NDEBUG
#ifndef NDEBUG
auto Known = basicBlockNames.find(block);
if (Known == basicBlockNames.end())
return None;

return StringRef(Known->second);
#else
#else
return None;
#endif
#endif
}

/// Serialize a SIL module using the configured SerializeSILAction.
Expand Down
69 changes: 44 additions & 25 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsSema.h"
#include "swift/AST/DistributedDecl.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/FileUnit.h"
#include "swift/AST/ForeignAsyncConvention.h"
Expand Down Expand Up @@ -1257,35 +1258,53 @@ FuncDecl *ASTContext::getEqualIntDecl() const {
return getBinaryComparisonOperatorIntDecl(*this, "==", getImpl().EqualIntDecl);
}

AbstractFunctionDecl *ASTContext::getRemoteCallOnDistributedActorSystem(
NominalTypeDecl *actorOrSystem, bool isVoidReturn) const {
assert(actorOrSystem && "distributed actor (or system) decl must be provided");
const NominalTypeDecl *system = actorOrSystem;
if (actorOrSystem->isDistributedActor()) {
auto var = actorOrSystem->getDistributedActorSystemProperty();
system = var->getInterfaceType()->getAnyNominal();
}
//AbstractFunctionDecl *ASTContext::getRemoteCallOnDistributedActorSystem(
// NominalTypeDecl *actorOrSystem, bool isVoidReturn) const {
// assert(actorOrSystem && "distributed actor (or system) decl must be provided");
// const NominalTypeDecl *system = actorOrSystem;
// if (actorOrSystem->isDistributedActor()) {
//
// auto var = actorOrSystem->getDistributedActorSystemProperty();
// system = var->getInterfaceType()->getAnyNominal();
// }
//
// if (!system)
// system = getProtocol(KnownProtocolKind::DistributedActorSystem);
//
// auto mutableSystem = const_cast<NominalTypeDecl *>(system);
// return evaluateOrDefault(
// system->getASTContext().evaluator,
// GetDistributedActorSystemRemoteCallFunctionRequest{mutableSystem, /*isVoidReturn=*/isVoidReturn},
// nullptr);
//}

FuncDecl *ASTContext::getMakeInvocationEncoderOnDistributedActorSystem(
AbstractFunctionDecl *thunk) const {
// NominalTypeDecl *system = actorOrSystem;
// assert(actorOrSystem && "distributed actor (or system) decl must be provided");
// if (actorOrSystem->isDistributedActor()) {
// auto ty = getDistributedActorSystemType(actorOrSystem);
// fprintf(stderr, "[%s:%d] (%s) getDistributedActorSystemType(actorOrSystem)\n", __FILE__, __LINE__, __FUNCTION__);
// ty.dump();
//
// auto actor = actorOrSystem;
// auto var = actor->getDistributedActorSystemProperty();
// assert(var && "Could not locate 'actorSystem' property!");
// system = var->getInterfaceType()->getAnyNominal();
// }

if (!system)
system = getProtocol(KnownProtocolKind::DistributedActorSystem);
auto systemTy = getConcreteReplacementForProtocolActorSystemType(thunk);
assert(systemTy && "No specific ActorSystem type found!");
fprintf(stderr, "[%s:%d] (%s) FOUND SYSTEM TYPE: %s\n", __FILE__, __LINE__, __FUNCTION__, systemTy->getAnyNominal()->getName().str().str().c_str());

auto mutableSystem = const_cast<NominalTypeDecl *>(system);
return evaluateOrDefault(
system->getASTContext().evaluator,
GetDistributedActorSystemRemoteCallFunctionRequest{mutableSystem, /*isVoidReturn=*/isVoidReturn},
nullptr);
}
auto systemNominal = systemTy->getNominalOrBoundGenericNominal();
assert(systemNominal && "No system nominal type found!");

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();
}
// // NO, since we need the specific one
// auto &C = thunk->getASTContext();
// auto systemNominal = C.getProtocol(KnownProtocolKind::DistributedActorSystem);

for (auto result : system->lookupDirect(Id_makeInvocationEncoder)) {
for (auto result : systemNominal->lookupDirect(Id_makeInvocationEncoder)) {
auto *fd = dyn_cast<FuncDecl>(result);
if (!fd)
continue;
Expand Down
5 changes: 0 additions & 5 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5294,11 +5294,6 @@ bool ProtocolDecl::isMarkerProtocol() const {
return getAttrs().hasAttribute<MarkerAttr>();
}

bool ProtocolDecl::inheritsFromDistributedActor() const {
auto &C = getASTContext();
return inheritsFrom(C.getDistributedActorDecl());
}

ArrayRef<ProtocolDecl *> ProtocolDecl::getInheritedProtocols() const {
auto *mutThis = const_cast<ProtocolDecl *>(this);
return evaluateOrDefault(getASTContext().evaluator,
Expand Down
83 changes: 70 additions & 13 deletions lib/AST/DistributedDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements the Decl class and subclasses.
// This file handles lookups related to distributed actor decls.
//
//===----------------------------------------------------------------------===//

Expand Down Expand Up @@ -65,19 +65,51 @@ using namespace swift;
/************** Distributed Actor System Associated Types *********************/
/******************************************************************************/

Type swift::getDistributedActorSystemType(NominalTypeDecl *actor) {
Type swift::getConcreteReplacementForProtocolActorSystemType(ValueDecl *member) {
auto &C = member->getASTContext();
auto *DC = member->getDeclContext();
auto DA = C.getDistributedActorDecl();

// === When declared inside an actor, we can get the type directly
if (auto classDecl = DC->getSelfClassDecl()) {
return getDistributedActorSystemType(classDecl);
}

/// === Maybe the value is declared in a protocol?
if (auto protocol = DC->getSelfProtocolDecl()) {
GenericSignature signature;
if (auto *genericContext = member->getAsGenericContext()) {
signature = genericContext->getGenericSignature();
} else {
signature = DC->getGenericSignatureOfContext();
}

auto ActorSystemAssocType =
DA->getAssociatedType(C.Id_ActorSystem)->getDeclaredInterfaceType();

auto systemTy = signature->getConcreteType(ActorSystemAssocType);
assert(systemTy && "couldn't find concrete type for actor system");
return systemTy;
}

llvm_unreachable("Unable to fetch ActorSystem type!");
}

Type swift::getDistributedActorSystemType(ClassDecl *actor) {
// assert(!isa<ProtocolDecl>(nominal) && "FIXME: we should deal with it here too or collapse the two impls");
assert(actor->isDistributedActor());
auto &ctx = actor->getASTContext();
auto &C = actor->getASTContext();
auto *DC = actor->getDeclContext();

auto protocol = ctx.getProtocol(KnownProtocolKind::DistributedActor);
if (!protocol)
return ErrorType::get(ctx);
auto DA = C.getDistributedActorDecl();
if (!DA)
return ErrorType::get(C);

// Dig out the actor system type.
auto module = actor->getParentModule();
Type selfType = actor->getSelfInterfaceType();
auto conformance = module->lookupConformance(selfType, protocol);
return conformance.getTypeWitnessByName(selfType, ctx.Id_ActorSystem);
auto conformance = module->lookupConformance(selfType, DA);
return conformance.getTypeWitnessByName(selfType, C.Id_ActorSystem);
}

Type swift::getDistributedActorIDType(NominalTypeDecl *actor) {
Expand All @@ -89,7 +121,7 @@ Type swift::getDistributedActorSystemActorIDRequirementType(NominalTypeDecl *sys
assert(!system->isDistributedActor());
auto &ctx = system->getASTContext();

auto protocol = ctx.getProtocol(KnownProtocolKind::DistributedActorSystem);
auto protocol = ctx.getDistributedActorSystemDecl();
if (!protocol)
return Type();

Expand Down Expand Up @@ -128,7 +160,7 @@ Type ASTContext::getAssociatedTypeOfDistributedSystemOfActor(
if (!actorSystemDecl)
return Type();

auto actorSystemProtocol = ctx.getProtocol(KnownProtocolKind::DistributedActorSystem);
auto actorSystemProtocol = ctx.getDistributedActorSystemDecl();
if (!actorSystemProtocol)
return Type();

Expand Down Expand Up @@ -252,7 +284,7 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)

// === Must be declared in a 'DistributedActorSystem' conforming type
ProtocolDecl *systemProto =
C.getProtocol(KnownProtocolKind::DistributedActorSystem);
C.getDistributedActorSystemDecl();

auto systemNominal = getDeclContext()->getSelfNominalTypeDecl();
auto distSystemConformance = module->lookupConformance(
Expand Down Expand Up @@ -968,7 +1000,7 @@ llvm::SmallPtrSet<ProtocolDecl *, 2>
swift::extractDistributedSerializationRequirements(
ASTContext &C, ArrayRef<Requirement> allRequirements) {
llvm::SmallPtrSet<ProtocolDecl *, 2> serializationReqs;
auto systemProto = C.getProtocol(KnownProtocolKind::DistributedActorSystem);
auto systemProto = C.getDistributedActorSystemDecl();
auto serializationReqAssocType =
systemProto->getAssociatedType(C.Id_SerializationRequirement);
auto systemSerializationReqTy = serializationReqAssocType->getInterfaceType();
Expand Down Expand Up @@ -1024,6 +1056,31 @@ NominalTypeDecl::getDistributedRemoteCallTargetInitFunction() const {
GetDistributedRemoteCallTargetInitFunctionRequest(mutableThis), nullptr);
}

AbstractFunctionDecl *ASTContext::getRemoteCallOnDistributedActorSystem(
NominalTypeDecl *actorOrSystem, bool isVoidReturn) const {
assert(actorOrSystem && "distributed actor (or system) decl must be provided");
const NominalTypeDecl *system = actorOrSystem;
if (actorOrSystem->isDistributedActor()) {
auto systemTy = getConcreteReplacementForProtocolActorSystemType(actorOrSystem);
fprintf(stderr, "[%s:%d] (%s) systemTy\n", __FILE__, __LINE__, __FUNCTION__);
systemTy.dump();

system = systemTy->getNominalOrBoundGenericNominal();
system->dump();
// auto var = actorOrSystem->getDistributedActorSystemProperty();
// system = var->getInterfaceType()->getAnyNominal();
}

if (!system)
system = getProtocol(KnownProtocolKind::DistributedActorSystem);

auto mutableSystem = const_cast<NominalTypeDecl *>(system);
return evaluateOrDefault(
system->getASTContext().evaluator,
GetDistributedActorSystemRemoteCallFunctionRequest{mutableSystem, /*isVoidReturn=*/isVoidReturn},
nullptr);
}

/******************************************************************************/
/********************** Distributed Actor Properties **************************/
/******************************************************************************/
Expand Down
Loading