1515#include " RValue.h"
1616#include " Scope.h"
1717#include " swift/AST/ASTContext.h"
18+ #include " swift/AST/ProtocolConformance.h"
1819#include " swift/Basic/Range.h"
1920
2021using namespace swift ;
@@ -242,11 +243,12 @@ ManagedValue SILGenFunction::emitNonIsolatedIsolation(SILLocation loc) {
242243
243244SILValue SILGenFunction::emitLoadGlobalActorExecutor (Type globalActor) {
244245 auto loc = RegularLocation::getAutoGeneratedLocation (F.getLocation ());
245- auto actor = emitLoadOfGlobalActorShared (loc, globalActor->getCanonicalType ());
246- return emitLoadActorExecutor (loc, actor);
246+ auto actorAndFormalType =
247+ emitLoadOfGlobalActorShared (loc, globalActor->getCanonicalType ());
248+ return emitLoadActorExecutor (loc, actorAndFormalType.first );
247249}
248250
249- ManagedValue
251+ std::pair< ManagedValue, CanType>
250252SILGenFunction::emitLoadOfGlobalActorShared (SILLocation loc, CanType actorType) {
251253 NominalTypeDecl *nominal = actorType->getNominalOrBoundGenericNominal ();
252254 VarDecl *sharedInstanceDecl = nominal->getGlobalActorInstance ();
@@ -270,18 +272,53 @@ SILGenFunction::emitLoadOfGlobalActorShared(SILLocation loc, CanType actorType)
270272 actorMetaType, /* isSuper*/ false , sharedInstanceDecl, PreparedArguments (),
271273 subs, AccessSemantics::Ordinary, instanceType, SGFContext ());
272274 ManagedValue actorInstance = std::move (actorInstanceRV).getScalarValue ();
273- return actorInstance;
275+ return { actorInstance, instanceType-> getCanonicalType ()} ;
274276}
275277
276278ManagedValue
277279SILGenFunction::emitGlobalActorIsolation (SILLocation loc,
278280 CanType globalActorType) {
279- // GlobalActor .shared returns Self, so this should be a value of
280- // GlobalActor type.
281- auto actor = emitLoadOfGlobalActorShared (loc, globalActorType);
281+ // Load the .shared property. Note that this isn't necessarily a value
282+ // of the global actor type.
283+ auto actorAndFormalType = emitLoadOfGlobalActorShared (loc, globalActorType);
282284
283285 // Since it's just a normal actor instance, we can use the normal path.
284- return emitActorInstanceIsolation (loc, actor, globalActorType);
286+ return emitActorInstanceIsolation (loc, actorAndFormalType.first ,
287+ actorAndFormalType.second );
288+ }
289+
290+ // / Given a value of some non-optional distributed actor type, convert it
291+ // / to the non-optional `any Actor` type.
292+ static ManagedValue
293+ emitDistributedActorIsolation (SILGenFunction &SGF, SILLocation loc,
294+ ManagedValue actor, CanType actorType) {
295+ // First, open the actor type if it's an existential type.
296+ if (actorType->isExistentialType ()) {
297+ CanType openedType = OpenedArchetypeType::getAny (actorType,
298+ SGF.F .getGenericSignature ());
299+ SILType loweredOpenedType = SGF.getLoweredType (openedType);
300+
301+ actor = SGF.emitOpenExistential (loc, actor, loweredOpenedType,
302+ AccessKind::Read);
303+ actorType = openedType;
304+ }
305+
306+ auto &ctx = SGF.getASTContext ();
307+ auto distributedActorProto =
308+ ctx.getProtocol (KnownProtocolKind::DistributedActor);
309+
310+ // Build <T: DistributedActor> and its substitutions for actorType.
311+ // Doing this manually is ill-advised in general, but this is such a
312+ // simple case that it's okay.
313+ auto sig = distributedActorProto->getGenericSignature ();
314+ auto distributedActorConf =
315+ SGF.SGM .SwiftModule ->lookupConformance (actorType, distributedActorProto);
316+ auto distributedActorSubs = SubstitutionMap::get (sig, {actorType},
317+ {distributedActorConf});
318+
319+ // Use that to build the magical conformance to Actor for the distributed
320+ // actor type.
321+ return SGF.emitDistributedActorAsAnyActor (loc, distributedActorSubs, actor);
285322}
286323
287324// / Given a value of some non-optional actor type, convert it to
@@ -295,6 +332,13 @@ emitNonOptionalActorInstanceIsolation(SILGenFunction &SGF, SILLocation loc,
295332 return actor;
296333
297334 CanType anyActorType = anyActorTy.getASTType ();
335+
336+ // If the actor is a distributed actor, (1) it had better be local
337+ // and (2) we need to use the special conformance.
338+ if (actorType->isDistributedActor ()) {
339+ return emitDistributedActorIsolation (SGF, loc, actor, actorType);
340+ }
341+
298342 return SGF.emitTransformExistential (loc, actor, actorType, anyActorType);
299343}
300344
@@ -587,3 +631,76 @@ SILValue SILGenFunction::emitGetCurrentExecutor(SILLocation loc) {
587631 assert (ExpectedExecutor && " prolog failed to set up expected executor?" );
588632 return ExpectedExecutor;
589633}
634+
635+ // / Find the extension on DistributedActor that defines __actorUnownedExecutor.
636+ static ExtensionDecl *findDistributedActorAsActorExtension (
637+ ProtocolDecl *distributedActorProto, ModuleDecl *module ) {
638+ ASTContext &ctx = distributedActorProto->getASTContext ();
639+ auto name = ctx.getIdentifier (" __actorUnownedExecutor" );
640+ auto results = distributedActorProto->lookupDirect (
641+ name, SourceLoc (),
642+ NominalTypeDecl::LookupDirectFlags::IncludeAttrImplements);
643+ for (auto result : results) {
644+ if (auto var = dyn_cast<VarDecl>(result)) {
645+ return dyn_cast<ExtensionDecl>(var->getDeclContext ());
646+ }
647+ }
648+
649+ return nullptr ;
650+ }
651+
652+ ProtocolConformanceRef
653+ SILGenModule::getDistributedActorAsActorConformance (SubstitutionMap subs) {
654+ ASTContext &ctx = M.getASTContext ();
655+ auto actorProto = ctx.getProtocol (KnownProtocolKind::Actor);
656+ Type distributedActorType = subs.getReplacementTypes ()[0 ];
657+
658+ if (!distributedActorAsActorConformance) {
659+ auto distributedActorProto = ctx.getProtocol (KnownProtocolKind::DistributedActor);
660+ if (!distributedActorProto)
661+ return ProtocolConformanceRef ();
662+
663+ auto ext = findDistributedActorAsActorExtension (
664+ distributedActorProto, M.getSwiftModule ());
665+ if (!ext)
666+ return ProtocolConformanceRef ();
667+
668+ // Conformance of DistributedActor to Actor.
669+ auto genericParam = subs.getGenericSignature ().getGenericParams ()[0 ];
670+ distributedActorAsActorConformance = ctx.getNormalConformance (
671+ Type (genericParam), actorProto, SourceLoc (), ext,
672+ ProtocolConformanceState::Incomplete, /* isUnchecked=*/ false ,
673+ /* isPreconcurrency=*/ false );
674+ }
675+
676+ return ProtocolConformanceRef (
677+ actorProto,
678+ ctx.getSpecializedConformance (distributedActorType,
679+ distributedActorAsActorConformance,
680+ subs));
681+ }
682+
683+ ManagedValue
684+ SILGenFunction::emitDistributedActorAsAnyActor (SILLocation loc,
685+ SubstitutionMap distributedActorSubs,
686+ ManagedValue actorValue) {
687+ ProtocolConformanceRef conformances[1 ] = {
688+ SGM.getDistributedActorAsActorConformance (distributedActorSubs)
689+ };
690+
691+ // Erase the distributed actor instance into an `any Actor` existential with
692+ // the special conformance.
693+ auto &ctx = SGM.getASTContext ();
694+ CanType distributedActorType =
695+ distributedActorSubs.getReplacementTypes ()[0 ]->getCanonicalType ();
696+ auto &distributedActorTL = getTypeLowering (distributedActorType);
697+ auto actorProto = ctx.getProtocol (KnownProtocolKind::Actor);
698+ auto &anyActorTL = getTypeLowering (actorProto->getDeclaredExistentialType ());
699+ return emitExistentialErasure (loc, distributedActorType,
700+ distributedActorTL, anyActorTL,
701+ ctx.AllocateCopy (conformances),
702+ SGFContext (),
703+ [actorValue](SGFContext) {
704+ return actorValue;
705+ });
706+ }
0 commit comments