Skip to content

Support distributed actor init with a non-existential "transport" parameter #39811

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 56 additions & 59 deletions lib/SILGen/SILGenDistributed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,6 @@ static void emitDistributedActorStore_transport(
SILArgument *transportArg) {
auto &B = SGF.B;

auto &SGM = SGF.SGM;
SILGenFunctionBuilder builder(SGM);

auto *dc = func->getDeclContext();
auto classDecl = dc->getSelfClassDecl();

Expand All @@ -148,42 +145,36 @@ static void emitDistributedActorStore_transport(
loc, actorSelf, var,
SGF.getLoweredType(var->getInterfaceType()));

// ==== Store the transport
B.createCopyAddr(loc,
/*src*/transportArg,
/*dest*/fieldAddr,
IsNotTake, IsInitialization);
}

// TODO(distributed): remove this store impl and reuse Store_transport
static void
emitDistributedActor_init_transportStore(
SILGenFunction &SGF,
ManagedValue borrowedSelfArg, VarDecl *selfDecl,
ConstructorDecl *ctor,
Pattern *pattern, VarDecl *var) {
auto &C = selfDecl->getASTContext();
auto &B = SGF.B;
auto &F = SGF.F;
auto &SGM = SGF.SGM;
SILGenFunctionBuilder builder(SGM);

auto loc = SILLocation(ctor);
loc.markAutoGenerated();

// ==== Prepare assignment: get the self.transport address
SILValue transportArgValue = getActorTransportArgument(C, F, ctor);

// ----

auto transportFieldAddr = B.createRefElementAddr(
loc, borrowedSelfArg.getValue(), var,
SGF.getLoweredType(var->getInterfaceType()));
// If the argument is not existential, it will be a concrete type
// that can be erased to that existential.
SILValue transportValue = transportArg;
if (!transportArg->getType().isExistentialType()) {
auto &existentialTL = SGF.getTypeLowering(var->getInterfaceType());
auto concreteFormalType = transportArg->getType().getASTType();

auto archetype = OpenedArchetypeType::getAny(var->getInterfaceType());
AbstractionPattern abstractionPattern(archetype);
auto &concreteTL = SGF.getTypeLowering(abstractionPattern,
concreteFormalType);

auto module = dc->getParentModule();
auto actorTransportProto = C.getProtocol(KnownProtocolKind::ActorTransport);
ProtocolConformanceRef conformances[] = {
module->lookupConformance(concreteFormalType, actorTransportProto) };
ManagedValue mv = SGF.emitExistentialErasure(loc, concreteFormalType,
concreteTL, existentialTL,
C.AllocateCopy(conformances),
SGFContext(),
[&](SGFContext C) -> ManagedValue {
return ManagedValue::forBorrowedRValue(transportArg);
});
transportValue = mv.getValue();
}

// ==== Store the transport
B.createCopyAddr(loc,
/*src*/transportArgValue,
/*dest*/transportFieldAddr,
/*src*/transportValue,
/*dest*/fieldAddr,
IsNotTake, IsInitialization);
}

Expand Down Expand Up @@ -254,14 +245,17 @@ static void emitDistributedActorStore_init_assignIdentity(
assert(distributedActorProto);
assert(transportProto);

// --- Open the transport existential
OpenedArchetypeType *Opened;
// --- Open the transport existential, if needed.
SILValue transportValue = transportArgValue;
auto transportASTType = transportArgValue->getType().getASTType();
auto openedTransportType =
transportASTType->openAnyExistentialType(Opened)->getCanonicalType();
auto openedTransportSILType = F.getLoweredType(openedTransportType);
auto transportArchetypeValue = B.createOpenExistentialAddr(
loc, transportArgValue, openedTransportSILType, OpenedExistentialAccess::Immutable);
if (transportASTType->isAnyExistentialType()) {
OpenedArchetypeType *Opened;
transportASTType =
transportASTType->openAnyExistentialType(Opened)->getCanonicalType();
transportValue = B.createOpenExistentialAddr(
loc, transportValue, F.getLoweredType(transportASTType),
OpenedExistentialAccess::Immutable);
}

// --- prepare `Self.self` metatype
auto *selfTyDecl = ctor->getParent()->getSelfNominalTypeDecl();
Expand Down Expand Up @@ -298,7 +292,7 @@ static void emitDistributedActorStore_init_assignIdentity(

auto assignWitnessMethod = B.createWitnessMethod(
loc,
/*lookupTy*/openedTransportType,
/*lookupTy*/transportASTType,
/*Conformance*/transportConfRef,
/*member*/assignIdentityRef,
/*methodTy*/assignIdentitySILTy);
Expand All @@ -308,7 +302,7 @@ static void emitDistributedActorStore_init_assignIdentity(

SubstitutionMap subs =
SubstitutionMap::get(genericSig,
{openedTransportType, selfTy},
{transportASTType, selfTy},
{transportConfRef, distributedActorConfRef});

// --- create a temporary storage for the result of the call
Expand All @@ -319,7 +313,7 @@ static void emitDistributedActorStore_init_assignIdentity(
// ---- actually call transport.assignIdentity(Self.self)
B.createApply(
loc, assignWitnessMethod, subs,
{ temp, selfMetatypeValue, transportArchetypeValue});
{ temp, selfMetatypeValue, transportValue});

// ==== Assign the identity to stored property
// TODO(distributed): reuse emitDistributedActorStore_id here, pass the SILValue
Expand Down Expand Up @@ -374,9 +368,9 @@ void SILGenFunction::initializeDistributedActorImplicitStorageInit(
if (var->getName() == C.Id_actorTransport &&
var->getInterfaceType()->isEqual(transportTy)) {
transportMember = var;
// TODO(distributed): reuse emitDistributedActorStore_transport
emitDistributedActor_init_transportStore(
*this, borrowedSelfArg, selfVarDecl, ctor, pattern, var);
emitDistributedActorStore_transport(
C, *this, borrowedSelfArg.getValue(), ctor,
getActorTransportArgument(C, F, ctor));
} else if (var->getName() == C.Id_id &&
(var->getInterfaceType()->isEqual(identityProtoTy) ||
var->getInterfaceType()->isEqual(anyIdentityTy))) { // TODO(distributed): stick one way to store, but today we can't yet store the existential
Expand Down Expand Up @@ -417,13 +411,16 @@ void SILGenFunction::emitDistributedActorReady(
assert(transportProto);

// --- Open the transport existential
OpenedArchetypeType *Opened;
auto transportASTType = transportArgValue->getType().getASTType();
auto openedTransportType =
transportASTType->openAnyExistentialType(Opened)->getCanonicalType();
auto openedTransportSILType = F.getLoweredType(openedTransportType);
auto transportArchetypeValue = B.createOpenExistentialAddr(
loc, transportArgValue, openedTransportSILType, OpenedExistentialAccess::Immutable);
SILValue transportValue = transportArgValue;
auto transportASTType = transportValue->getType().getASTType();
if (transportASTType->isAnyExistentialType()) {
OpenedArchetypeType *Opened;
transportASTType =
transportASTType->openAnyExistentialType(Opened)->getCanonicalType();
transportValue = B.createOpenExistentialAddr(
loc, transportValue, F.getLoweredType(transportASTType),
OpenedExistentialAccess::Immutable);
}

// === Make the transport.actorReady call
// --- prepare the witness_method
Expand Down Expand Up @@ -453,7 +450,7 @@ void SILGenFunction::emitDistributedActorReady(

auto readyWitnessMethod = B.createWitnessMethod(
loc,
/*lookupTy*/openedTransportType,
/*lookupTy*/transportASTType,
/*Conformance*/transportConfRef,
/*member*/actorReadyRef,
/*methodTy*/actorReadySILTy);
Expand All @@ -463,13 +460,13 @@ void SILGenFunction::emitDistributedActorReady(

SubstitutionMap subs =
SubstitutionMap::get(genericSig,
{openedTransportType, selfTy},
{transportASTType, selfTy},
{transportConfRef, distributedActorConfRef});

// ---- actually call transport.actorReady(self)
B.createApply(
loc, readyWitnessMethod, subs,
{ selfArgValue, transportArchetypeValue});
{ selfArgValue, transportValue});
}

/******************************************************************************/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,11 @@ distributed actor SimpleUserDefinedInitDistributedActor {
// While in AST the return was "return null" after SILGen we properly return the self
// CHECK: return %2 : $SimpleUserDefinedInitDistributedActor // id: %18
// CHECK: } // end sil function '$s41distributed_actor_user_transport_init_sil37SimpleUserDefinedInitDistributedActorC5other12theTransportACSi_01_K00lO0_ptcfc'

@available(SwiftStdlib 5.5, *)
distributed actor GenericUserDefinedInitDistributedActor {
// CHECK-LABEL: sil shared @$s41distributed_actor_user_transport_init_sil38GenericUserDefinedInitDistributedActorC0D0ACx_tc01_K00L9TransportRzlufcTf4gn_n : $@convention(method) <T where T : ActorTransport> (@in_guaranteed T, @owned GenericUserDefinedInitDistributedActor) -> @owned GenericUserDefinedInitDistributedActor
// CHECK: metatype $@thick GenericUserDefinedInitDistributedActor.Type
// CHECK: witness_method $T, #ActorTransport.assignIdentity
init<T: ActorTransport>(transport: T) { }
}