basic implementation of performing an init of the id after an assign of the actorSystem.

The resignID call within the initializer moved into DI, because an assignment to
the actorSystem, and thus initialization of the id, is no longer guaranteed to happen.
Thus, while we previously could model the resignation as a clean-up emitted on all
unwind paths in an initializer, now it's conditional, based on whether the id was
initialized. This is exactly what DI is designed to do, so we inject the resignation
call just before we call the identity's deinit.
This commit is contained in:
Kavon Farvardin
2022-03-15 18:20:00 -07:00
parent 13cbe0dd15
commit af683dc271
25 changed files with 290 additions and 117 deletions

View File

@@ -32,6 +32,13 @@ class SILLocation;
class SILType;
class SILValue;
/// Creates a reference to the distributed actor's \p actorSystem
/// stored property.
SILValue refDistributedActorSystem(SILBuilder &B,
SILLocation loc,
ClassDecl *actorDecl,
SILValue actorInstance);
/// Emit a call to a witness of the DistributedActorSystem protocol.
///
/// \param methodName The name of the method on the DistributedActorSystem protocol.
@@ -55,6 +62,11 @@ void emitDistributedActorSystemWitnessCall(
void emitActorReadyCall(SILBuilder &B, SILLocation loc, SILValue actor,
SILValue actorSystem);
/// Emits code to notify the \p actorSystem that the given identity is resigned.
void emitResignIdentityCall(SILBuilder &B, SILLocation loc, ClassDecl* actDecl,
SILValue actor, SILValue identityRef);
} // namespace swift
#endif

View File

@@ -0,0 +1,40 @@
//===--- InitializeDistActorIdentity.h - dist actor ID init for SILGen ----===//
//
// This source file is part of the Swift.org open source project
//
// 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
//
//===----------------------------------------------------------------------===//
#include "Cleanup.h"
namespace swift {
class AllocStackInst;
namespace Lowering {
/// A clean-up designed to emit an initialization of a distributed actor's
/// identity upon successful initialization of the actor's system.
struct InitializeDistActorIdentity : Cleanup {
private:
ConstructorDecl *ctor;
ManagedValue actorSelf;
VarDecl *systemVar;
public:
InitializeDistActorIdentity(ConstructorDecl *ctor, ManagedValue actorSelf);
void emit(SILGenFunction &SGF, CleanupLocation loc,
ForUnwind_t forUnwind) override;
void dump(SILGenFunction &) const override;
VarDecl* getSystemVar() const { return systemVar; }
};
} // end Lowering namespace
} // end swift namespace

View File

@@ -137,24 +137,24 @@ static SILArgument *findFirstDistributedActorSystemArg(SILFunction &F) {
auto *module = F.getModule().getSwiftModule();
auto &C = F.getASTContext();
auto *transportProto = C.getProtocol(KnownProtocolKind::DistributedActorSystem);
Type transportTy = transportProto->getDeclaredInterfaceType();
auto *DAS = C.getDistributedActorSystemDecl();
Type systemTy = DAS->getDeclaredInterfaceType();
for (auto arg : F.getArguments()) {
// TODO(distributed): also be able to locate a generic transport
// TODO(distributed): also be able to locate a generic system
Type argTy = arg->getType().getASTType();
auto argDecl = arg->getDecl();
auto conformsToTransport =
module->lookupConformance(argDecl->getInterfaceType(), transportProto);
auto conformsToSystem =
module->lookupConformance(argDecl->getInterfaceType(), DAS);
// Is it a protocol that conforms to DistributedActorSystem?
if (argTy->isEqual(transportTy) || conformsToTransport) {
if (argTy->isEqual(systemTy) || conformsToSystem) {
return arg;
}
// Is it some specific DistributedActorSystem?
auto result = module->lookupConformance(argTy, transportProto);
auto result = module->lookupConformance(argTy, DAS);
if (!result.isInvalid()) {
return arg;
}
@@ -172,7 +172,8 @@ static SILArgument *findFirstDistributedActorSystemArg(SILFunction &F) {
static void emitActorSystemInit(SILGenFunction &SGF,
ConstructorDecl *ctor,
SILLocation loc,
ManagedValue actorSelf) {
ManagedValue actorSelf,
SILValue systemValue) {
assert(ctor->isImplicit() && "unexpected explicit dist actor init");
assert(ctor->isDesignatedInit());
@@ -183,11 +184,10 @@ static void emitActorSystemInit(SILGenFunction &SGF,
// By construction, automatically generated distributed actor ctors have
// exactly one ActorSystem-conforming argument to the constructor,
// so we grab the first one from the params.
SILValue systemArg = findFirstDistributedActorSystemArg(SGF.F);
VarDecl *var = lookupProperty(classDecl, C.Id_actorSystem);
assert(var);
initializeProperty(SGF, loc, actorSelf.getValue(), var, systemArg);
initializeProperty(SGF, loc, actorSelf.getValue(), var, systemValue);
}
/// Emits the distributed actor's identity (`id`) initialization.
@@ -196,72 +196,98 @@ static void emitActorSystemInit(SILGenFunction &SGF,
/// \verbatim
/// self.id = system.assignID(Self.self)
/// \endverbatim
static void emitIDInit(SILGenFunction &SGF, ConstructorDecl *ctor,
SILLocation loc, ManagedValue borrowedSelfArg) {
assert(ctor->isImplicit() && "unexpected explicit dist actor init");
void SILGenFunction::emitDistActorIdentityInit(ConstructorDecl *ctor,
SILLocation loc,
SILValue borrowedSelfArg,
SILValue actorSystem) {
assert(ctor->isDesignatedInit());
auto &C = ctor->getASTContext();
auto &B = SGF.B;
auto &F = SGF.F;
auto *dc = ctor->getDeclContext();
auto classDecl = dc->getSelfClassDecl();
assert(classDecl->isDistributedActor());
// --- prepare `Self.self` metatype
auto *selfTyDecl = ctor->getParent()->getSelfNominalTypeDecl();
auto selfTy = F.mapTypeIntoContext(selfTyDecl->getDeclaredInterfaceType());
auto selfMetatype = SGF.getLoweredType(MetatypeType::get(selfTy));
auto selfMetatype = getLoweredType(MetatypeType::get(selfTy));
SILValue selfMetatypeValue = B.createMetatype(loc, selfMetatype);
// since we're doing this only for the implicitly defined ctors, grab from arg
SILValue actorSystem = findFirstDistributedActorSystemArg(SGF.F);
// --- create a temporary storage for the result of the call
// it will be deallocated automatically as we exit this scope
VarDecl *var = lookupProperty(classDecl, C.Id_id);
auto resultTy = SGF.getLoweredType(
F.mapTypeIntoContext(var->getInterfaceType()));
auto temp = SGF.emitTemporaryAllocation(loc, resultTy);
auto resultTy = getLoweredType(F.mapTypeIntoContext(var->getInterfaceType()));
auto temp = emitTemporaryAllocation(loc, resultTy);
// --- emit the call itself.
emitDistributedActorSystemWitnessCall(
B, loc, C.Id_assignID,
actorSystem, SGF.getLoweredType(selfTy),
actorSystem, getLoweredType(selfTy),
{ temp, selfMetatypeValue });
// --- initialize the property.
initializeProperty(SGF, loc, borrowedSelfArg.getValue(), var, temp);
initializeProperty(*this, loc, borrowedSelfArg, var, temp);
}
namespace {
/// Cleanup to resign the identity of a distributed actor if an abnormal exit happens.
class ResignIdentity : public Cleanup {
ClassDecl *actorDecl;
SILValue self;
public:
ResignIdentity(ClassDecl *actorDecl, SILValue self)
: actorDecl(actorDecl), self(self) {
assert(actorDecl->isDistributedActor());
}
InitializeDistActorIdentity::InitializeDistActorIdentity(ConstructorDecl *ctor,
ManagedValue actorSelf)
: ctor(ctor),
actorSelf(actorSelf) {
systemVar = ctor->getDeclContext()
->getSelfClassDecl()
->getDistributedActorSystemProperty();
assert(systemVar);
}
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
if (forUnwind == IsForUnwind) {
l.markAutoGenerated();
SGF.emitDistributedActorSystemResignIDCall(l, actorDecl,
ManagedValue::forUnmanaged(self));
}
void InitializeDistActorIdentity::emit(SILGenFunction &SGF, CleanupLocation loc,
ForUnwind_t forUnwind) {
// If we're unwinding, that must mean we're in the case where the
// evaluating the expression being assigned to the actorSystem has
// thrown an error. In that case, we cannot initialize the identity,
// since there is no actorSystem.
if (forUnwind == IsForUnwind)
return;
// Save the current clean-up depth
auto baseDepth = SGF.getCleanupsDepth();
{
loc.markAutoGenerated();
auto borrowedSelf = actorSelf.borrow(SGF, loc);
// load the actorSystem value
Type formalType = SGF.F.mapTypeIntoContext(systemVar->getInterfaceType());
SILType loweredType = SGF.getLoweredType(formalType).getAddressType();
auto ref =
SGF.B.createRefElementAddr(loc, borrowedSelf, systemVar, loweredType);
SGFContext ctx;
auto systemVal =
SGF.emitLoad(loc, ref.getValue(),
SGF.getTypeLowering(loweredType), ctx, IsNotTake);
// Important that we mark the location as auto-generated, since the id
// is a @_compilerInitialized field.
SGF.emitDistActorIdentityInit(ctor, loc,
borrowedSelf.getValue(), systemVal.getValue());
}
void dump(SILGenFunction &SGF) const override {
// Emit any active clean-ups we just pushed.
while (SGF.getTopCleanup() != baseDepth)
SGF.Cleanups.popAndEmitCleanup(SGF.getTopCleanup(), loc, forUnwind);
}
void InitializeDistActorIdentity::dump(SILGenFunction &) const {
#ifndef NDEBUG
llvm::errs() << "ResignIdentity "
<< "State:" << getState() << " "
<< "Self: " << self << "\n";
llvm::errs() << "InitializeDistActorIdentity\n"
<< "State: " << getState()
<< "\n";
#endif
}
};
} // end anonymous namespace
}
void SILGenFunction::emitDistributedActorImplicitPropertyInits(
ConstructorDecl *ctor, ManagedValue selfArg) {
@@ -273,18 +299,18 @@ void SILGenFunction::emitDistributedActorImplicitPropertyInits(
selfArg = selfArg.borrow(*this, loc);
// register a clean-up to resign the identity upon abnormal exit
// we do this regardless of initializer kind, since it's easy to do in SILGen.
auto *actorDecl = cast<ClassDecl>(ctor->getParent()->getAsDecl());
Cleanups.pushCleanup<ResignIdentity>(actorDecl, selfArg.getValue());
// Users must initialize the actorSystem property explicitly in their ctors
if (!ctor->isImplicit())
// implicit ctors initialize the system and identity from
// its ActorSystem parameter.
if (ctor->isImplicit()) {
SILValue actorSystem = findFirstDistributedActorSystemArg(F);
emitActorSystemInit(*this, ctor, loc, selfArg, actorSystem);
emitDistActorIdentityInit(ctor, loc, selfArg.getValue(), actorSystem);
return;
}
// implicit ctors initialize these from the ActorSystem parameter.
emitActorSystemInit(*this, ctor, loc, selfArg);
emitIDInit(*this, ctor, loc, selfArg);
// for explicit ctors, store (but do not push) a clean-up that will
// initialize the identity in whichever scope it's pushed to.
DistActorCtorContext = InitializeDistActorIdentity(ctor, selfArg);
}
void SILGenFunction::emitDistributedActorReady(
@@ -505,7 +531,7 @@ SILGenFunction::emitConditionalResignIdentityCall(SILLocation loc,
ManagedValue actorSelf,
SILBasicBlock *continueBB) {
assert(actorDecl->isDistributedActor() &&
"only distributed actors have transport lifecycle hooks in deinit");
"only distributed actors have actorSystem lifecycle hooks in deinit");
auto selfTy = actorDecl->getDeclaredInterfaceType();

View File

@@ -15,6 +15,7 @@
#include "FormalEvaluation.h"
#include "Initialization.h"
#include "InitializeDistActorIdentity.h"
#include "JumpDest.h"
#include "RValue.h"
#include "SGFContext.h"
@@ -399,6 +400,11 @@ public:
AsyncLetChildTask>
AsyncLetChildTasks;
/// Indicates whether this function is a distributed actor's designated
/// initializer, providing the needed clean-up to emit an identity
/// assignment after initializing the actorSystem property.
Optional<InitializeDistActorIdentity> DistActorCtorContext;
/// When rebinding 'self' during an initializer delegation, we have to be
/// careful to preserve the object at 1 retain count during the delegation
/// because of assumptions in framework code. This enum tracks the state of
@@ -2071,6 +2077,17 @@ public:
void emitDistributedActorImplicitPropertyInits(
ConstructorDecl *ctor, ManagedValue selfArg);
/// Initializes just the implicit identity property of a distributed actor.
/// \param selfVal a value corresponding to the actor's self
/// \param actorSystemVal a value corresponding to the actorSystem, to be used
/// to invoke its \p assignIdentity method.
void emitDistActorIdentityInit(ConstructorDecl *ctor,
SILLocation loc,
SILValue selfVal,
SILValue actorSystemVal);
void registerDistActorIdentityInit();
/// Given a function representing a distributed actor factory, emits the
/// corresponding SIL function for it.
void emitDistributedActorFactory(

View File

@@ -749,6 +749,8 @@ namespace {
virtual bool isLoadingPure() const override { return true; }
VarDecl *getField() const { return Field; }
ManagedValue project(SILGenFunction &SGF, SILLocation loc,
ManagedValue base) && override {
assert(base.getType().hasReferenceSemantics() &&
@@ -4505,6 +4507,18 @@ void SILGenFunction::emitAssignToLValue(SILLocation loc, RValue &&src,
emitAssignToLValue(loc, ArgumentSource(loc, std::move(src)), std::move(dest));
}
namespace {
} // end anonymous namespace
/// Checks if the last component of the LValue refers to the given var decl.
static bool referencesVar(PathComponent const& comp, VarDecl *var) {
if (comp.getKind() != PathComponent::RefElementKind)
return false;
return static_cast<RefElementComponent const&>(comp).getField() == var;
}
void SILGenFunction::emitAssignToLValue(SILLocation loc,
ArgumentSource &&src,
LValue &&dest) {
@@ -4514,6 +4528,12 @@ void SILGenFunction::emitAssignToLValue(SILLocation loc,
// LValue. For example: (x[i], x[j]) = a, b
ArgumentScope argScope(*this, loc);
// If this is an assignment to a distributed actor's actorSystem, push
// a clean-up to also initialize its id.
if (LLVM_UNLIKELY(DistActorCtorContext) &&
referencesVar(**(dest.end()-1), DistActorCtorContext->getSystemVar()))
Cleanups.pushCleanup<InitializeDistActorIdentity>(*DistActorCtorContext);
// If the last component is a getter/setter component, use a special
// generation pattern that allows us to peephole the emission of the RHS.
if (trySetterPeephole(*this, loc, std::move(src), std::move(dest))) {
@@ -4605,6 +4625,13 @@ void SILGenFunction::emitAssignLValueToLValue(SILLocation loc, LValue &&src,
return;
}
// If this is an assignment to a distributed actor's actorSystem, push
// a clean-up to also initialize its id.
// FIXME: in what situations does this lvalue to lvalue assign happen?
if (LLVM_UNLIKELY(DistActorCtorContext) &&
referencesVar(**(dest.end()-1), DistActorCtorContext->getSystemVar()))
Cleanups.pushCleanup<InitializeDistActorIdentity>(*DistActorCtorContext);
auto &rvalueTL = getTypeLowering(src.getTypeOfRValue());
auto srcAddr = emitAddressOfLValue(loc, std::move(src)).getUnmanagedValue();

View File

@@ -17,6 +17,7 @@
#include "swift/SIL/InstructionUtils.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SILOptimizer/Utils/DistributedActor.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/SaveAndRestore.h"
@@ -223,6 +224,33 @@ SILType DIMemoryObjectInfo::getElementType(unsigned EltNo) const {
Module, MemorySILType, EltNo, isNonDelegatingInit());
}
/// During tear-down of a distributed actor, we must invoke its
/// \p actorSystem.resignID method, passing in the \p id from the
/// instance. Thus, this function inspects the VarDecl about to be destroyed
/// and if it matches the \p id, the \p resignIdentity call is emitted.
///
/// NOTE (id-before-actorSystem): it is crucial that the \p id is
/// deinitialized before the \p actorSystem is deinitialized, because
/// resigning the identity requires a call into the \p actorSystem.
/// Since deinitialization consistently happens in-order, according to the
/// listing returned by \p NominalTypeDecl::getStoredProperties
/// it is important the the VarDecl for the \p id is synthesized before
/// the \p actorSystem so that we get the right ordering in DI and deinits.
///
/// \param nomDecl a distributed actor decl
/// \param var a VarDecl that is a member of the \p nomDecl
static void tryToResignIdentity(SILLocation loc, SILBuilder &B,
NominalTypeDecl* nomDecl, VarDecl *var,
SILValue idRef, SILValue actorInst) {
assert(nomDecl->isDistributedActor());
if (var != nomDecl->getDistributedActorIDProperty())
return;
emitResignIdentityCall(B, loc, cast<ClassDecl>(nomDecl),
actorInst, idRef);
}
/// Given a tuple element number (in the flattened sense) return a pointer to a
/// leaf element of the specified number, so we can insert destroys for it.
SILValue DIMemoryObjectInfo::emitElementAddressForDestroy(
@@ -262,6 +290,7 @@ SILValue DIMemoryObjectInfo::emitElementAddressForDestroy(
// lifetimes for each of the tuple members.
if (IsSelf) {
if (auto *NTD = PointeeType.getNominalOrBoundGenericNominal()) {
const bool IsDistributedActor = NTD->isDistributedActor();
bool HasStoredProperties = false;
for (auto *VD : NTD->getStoredProperties()) {
if (!HasStoredProperties) {
@@ -289,10 +318,15 @@ SILValue DIMemoryObjectInfo::emitElementAddressForDestroy(
Borrowed = Ptr = B.createBeginBorrow(Loc, Ptr);
EndScopeList.emplace_back(Borrowed, EndScopeKind::Borrow);
}
SILValue Self = Ptr;
Ptr = B.createRefElementAddr(Loc, Ptr, VD);
Ptr = B.createBeginAccess(
Loc, Ptr, SILAccessKind::Deinit, SILAccessEnforcement::Static,
false /*noNestedConflict*/, false /*fromBuiltin*/);
if (IsDistributedActor)
tryToResignIdentity(Loc, B, NTD, VD, Ptr, Self);
EndScopeList.emplace_back(Ptr, EndScopeKind::Access);
}

View File

@@ -788,48 +788,14 @@ void LifetimeChecker::diagnoseBadExplicitStore(SILInstruction *Inst) {
/// Determines whether the given function is a constructor that belogs to a
/// distributed actor declaration.
static bool isDistributedActorCtor(SILFunction &F) {
/// \returns nullptr if false, and the class decl for the actor otherwise.
static ClassDecl* getDistributedActorOfCtor(SILFunction &F) {
auto *context = F.getDeclContext();
if (auto *ctor = dyn_cast_or_null<ConstructorDecl>(context->getAsDecl()))
if (auto *cls = dyn_cast<ClassDecl>(ctor->getDeclContext()->getAsDecl()))
return cls->isDistributedActor();
return false;
}
//static SILValue emitActorPropertyReference(
// SILGenFunction &SGF, SILLocation loc, SILValue actorSelf,
// VarDecl *property) {
// Type formalType = SGF.F.mapTypeIntoContext(property->getInterfaceType());
// SILType loweredType = SGF.getLoweredType(formalType).getAddressType();
// return SGF.B.createRefElementAddr(loc, actorSelf, property, loweredType);
//}
/// Creates a reference to the distributed actor's \p actorSystem
/// stored property.
static SILValue refDistributedActorSystem(SILLocation loc,
SILBuilder &b,
SILValue actorInstance,
SILFunction &F) {
ClassDecl *clsDecl = F.getDeclContext()->getSelfClassDecl();
assert(clsDecl->isDistributedActor());
// get the VarDecl corresponding to the actorSystem.
auto refs = clsDecl->lookupDirect(clsDecl->getASTContext().Id_actorSystem);
assert(refs.size() == 1);
VarDecl *actorSystemVar = dyn_cast<VarDecl>(refs.front());
return b.createRefElementAddr(loc, actorInstance, actorSystemVar);
}
static void loadCopyWithCleanups(SILLocation loc, SILBuilder& b, SILValue ref,
llvm::function_ref<void(SILValue)> scope) {
auto copy = b.createLoad(loc, ref, LoadOwnershipQualifier::Copy);
auto borrow = b.createBeginBorrow(loc, copy);
scope(borrow);
b.createEndBorrow(loc, borrow);
b.createDestroyValue(loc, copy);
if (cls->isDistributedActor())
return cls;
return nullptr;
}
/// Injects a hop_to_executor instruction after the specified insertion point.
@@ -854,6 +820,7 @@ static void injectHopToExecutorAfter(SILLocation loc,
SILLocation genLoc = loc.asAutoGenerated();
const bool delegating = !TheMemory.isNonDelegatingInit();
SILValue val = TheMemory.getUninitializedValue();
auto &F = b.getFunction();
// delegating inits always have an alloc we need to load it from.
if (delegating)
@@ -861,16 +828,16 @@ static void injectHopToExecutorAfter(SILLocation loc,
SILValue actor = b.createBeginBorrow(genLoc, val);
b.createHopToExecutor(loc.asAutoGenerated(), actor, /*mandatory=*/false);
b.createHopToExecutor(genLoc, actor, /*mandatory=*/false);
// Distributed actors also need to notify their transport immediately
// after performing the hop.
if (!delegating && isDistributedActorCtor(b.getFunction())) {
SILValue systemRef = refDistributedActorSystem(loc.asAutoGenerated(),
b, actor, b.getFunction());
loadCopyWithCleanups(genLoc, b, systemRef, [&](SILValue systemVal) {
emitActorReadyCall(b, genLoc, actor, systemVal);
});
if (!delegating) {
if (auto *actorDecl = getDistributedActorOfCtor(F)) {
SILValue systemRef = refDistributedActorSystem(b, genLoc,
actorDecl, actor);
emitActorReadyCall(b, genLoc, actor, systemRef);
}
}
b.createEndBorrow(genLoc, actor);

View File

@@ -186,4 +186,36 @@ void emitActorReadyCall(SILBuilder &B, SILLocation loc, SILValue actor,
F.mapTypeIntoContext(actor->getType()), { actor });
}
void emitResignIdentityCall(SILBuilder &B, SILLocation loc,
ClassDecl* actorDecl,
SILValue actor, SILValue idRef) {
auto &F = B.getFunction();
auto &C = F.getASTContext();
SILValue systemRef = refDistributedActorSystem(B, loc, actorDecl, actor);
emitDistributedActorSystemWitnessCall(
B, loc, C.Id_resignID,
systemRef,
SILType(),
{ idRef });
}
/// Creates a reference to the distributed actor's \p actorSystem
/// stored property.
SILValue refDistributedActorSystem(SILBuilder &b,
SILLocation loc,
ClassDecl *actDecl,
SILValue actorInstance) {
assert(actDecl);
assert(actDecl->isDistributedActor());
// get the VarDecl corresponding to the actorSystem.
auto refs = actDecl->lookupDirect(actDecl->getASTContext().Id_actorSystem);
assert(refs.size() == 1);
VarDecl *actorSystemVar = dyn_cast<VarDecl>(refs.front());
return b.createRefElementAddr(loc, actorInstance, actorSystemVar);
}
} // namespace swift

View File

@@ -76,6 +76,10 @@ static VarDecl *addImplicitDistributedActorIDProperty(
// mark as nonisolated, allowing access to it from everywhere
propDecl->getAttrs().add(
new (C) NonisolatedAttr(/*IsImplicit=*/true));
// mark as @_compilerInitialized, since we synthesize the initializing
// assignment during SILGen.
propDecl->getAttrs().add(
new (C) CompilerInitializedAttr(/*IsImplicit=*/true));
nominal->addMember(propDecl);
nominal->addMember(pbDecl);

View File

@@ -629,6 +629,8 @@ void TypeChecker::checkDistributedActor(SourceFile *SF, NominalTypeDecl *nominal
// because the 'DerivedConformanceDistributedActor' won't trigger for 'id'
// because it has a default impl via 'Identifiable' (ObjectIdentifier)
// which we do not want.
// Also, the 'id' var must be added before the 'actorSystem'.
// See NOTE (id-before-actorSystem) for more details.
(void)nominal->getDistributedActorIDProperty();
}

View File

@@ -15,17 +15,23 @@ import Distributed
actor A {}
distributed actor DA {
init(system: FakeActorSystem) {}
init(system: FakeActorSystem) {
self.actorSystem = system
}
}
distributed actor DA_userDefined {
init(system: FakeActorSystem) {}
init(system: FakeActorSystem) {
self.actorSystem = system
}
deinit {}
}
distributed actor DA_userDefined2 {
init(system: FakeActorSystem) {}
init(system: FakeActorSystem) {
self.actorSystem = system
}
deinit {
print("Deinitializing \(self.id)")
@@ -37,7 +43,9 @@ distributed actor DA_state {
var name = "Hello"
var age = 42
init(system: FakeActorSystem) {}
init(system: FakeActorSystem) {
self.actorSystem = system
}
deinit {
print("Deinitializing \(self.id)")

View File

@@ -30,7 +30,7 @@ typealias DefaultDistributedActorSystem = FakeRoundtripActorSystem
static func main() async {
let system = DefaultDistributedActorSystem()
let actor = Worker(system: system)
let actor = Worker(actorSystem: system)
// CHECK: assign id: ActorAddress(address: "<unique-id>") for Worker
// compilation check:

View File

@@ -41,7 +41,7 @@ distributed actor Worker: LifecycleWatch {
@main struct Main {
static func main() async {
let worker: any LifecycleWatch = Worker(system: DefaultDistributedActorSystem())
let worker: any LifecycleWatch = Worker(actorSystem: DefaultDistributedActorSystem())
try! await worker.test()
// CHECK: executed: test()

View File

@@ -8,8 +8,6 @@
// UNSUPPORTED: use_os_stdlib
// UNSUPPORTED: back_deployment_runtime
// REQUIRES: radar_86543336
import Distributed
enum MyError: Error {

View File

@@ -35,7 +35,7 @@ distributed actor Worker {
static func main() async throws {
let system = LocalTestingDistributedActorSystem()
let actor = Worker(system: system)
let actor = Worker(actorSystem: system)
try await actor.hi() // local calls should still just work
// CHECK: hi!
}

View File

@@ -41,7 +41,7 @@ extension Greeter {
func test() async throws {
let system = DefaultDistributedActorSystem()
let g = Greeter(system: system)
let g = Greeter(actorSystem: system)
let greeter = try Greeter.resolve(id: g.id, using: system)
try await greeter.noParams()

View File

@@ -23,6 +23,7 @@ distributed actor SomeSpecificDistributedActor {
init(name: String, system: FakeActorSystem) {
self.name = name
self.surname = "Surname"
self.actorSystem = system
self.age = 42
}

View File

@@ -15,6 +15,7 @@ distributed actor MyDistActor {
let localOnlyField: SomeClass
init(system: FakeActorSystem) {
self.actorSystem = system
self.localOnlyField = SomeClass()
}
}

View File

@@ -23,6 +23,7 @@ distributed actor MyDistActor {
var localOnlyField: SomeClass
init(system_sync: FakeActorSystem) {
self.actorSystem = system_sync
self.localOnlyField = SomeClass()
}

View File

@@ -23,6 +23,7 @@ distributed actor MyDistActor {
var localOnlyField: SomeClass
init?(system_sync_fail: FakeActorSystem, cond: Bool) {
self.actorSystem = system_sync_fail
guard cond else { return nil }
self.localOnlyField = SomeClass()
}

View File

@@ -23,6 +23,7 @@ distributed actor MyDistActor {
var localOnlyField: SomeClass
init?(system_async_fail: FakeActorSystem, cond: Bool) async {
self.actorSystem = system_async_fail
guard cond else { return nil }
self.localOnlyField = SomeClass()
}

View File

@@ -23,6 +23,7 @@ distributed actor MyDistActor {
var localOnlyField: SomeClass
init?(system_async_fail_throws: FakeActorSystem, cond: Bool) async throws {
self.actorSystem = system_async_fail_throws
guard cond else { throw Err.blah }
self.localOnlyField = SomeClass()
}

View File

@@ -24,6 +24,7 @@ distributed actor MyDistActor {
var localOnlyField: SomeClass
init(system_async: FakeActorSystem, cond: Bool) async {
self.actorSystem = system_async
if cond {
self.localOnlyField = SomeClass()
}

View File

@@ -15,5 +15,5 @@ distributed actor DA {
func take<A: Codable>(actor: A) {}
func test(actorSystem: FakeActorSystem) {
take(actor: DA(system: actorSystem)) // ok
take(actor: DA(actorSystem: actorSystem)) // ok
}

View File

@@ -11,6 +11,5 @@ import Distributed
import def_distributed
func testDoSomethingDistributed(system: LocalTestingDistributedActorSystem) {
let _: DA = DA(system: system)
let _: DA = DA(actorSystem: system)
}