15
15
#include " RValue.h"
16
16
#include " Scope.h"
17
17
#include " swift/AST/ASTContext.h"
18
+ #include " swift/AST/ProtocolConformance.h"
18
19
#include " swift/Basic/Range.h"
19
20
20
21
using namespace swift ;
@@ -242,11 +243,12 @@ ManagedValue SILGenFunction::emitNonIsolatedIsolation(SILLocation loc) {
242
243
243
244
SILValue SILGenFunction::emitLoadGlobalActorExecutor (Type globalActor) {
244
245
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 );
247
249
}
248
250
249
- ManagedValue
251
+ std::pair< ManagedValue, CanType>
250
252
SILGenFunction::emitLoadOfGlobalActorShared (SILLocation loc, CanType actorType) {
251
253
NominalTypeDecl *nominal = actorType->getNominalOrBoundGenericNominal ();
252
254
VarDecl *sharedInstanceDecl = nominal->getGlobalActorInstance ();
@@ -270,18 +272,53 @@ SILGenFunction::emitLoadOfGlobalActorShared(SILLocation loc, CanType actorType)
270
272
actorMetaType, /* isSuper*/ false , sharedInstanceDecl, PreparedArguments (),
271
273
subs, AccessSemantics::Ordinary, instanceType, SGFContext ());
272
274
ManagedValue actorInstance = std::move (actorInstanceRV).getScalarValue ();
273
- return actorInstance;
275
+ return { actorInstance, instanceType-> getCanonicalType ()} ;
274
276
}
275
277
276
278
ManagedValue
277
279
SILGenFunction::emitGlobalActorIsolation (SILLocation loc,
278
280
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);
282
284
283
285
// 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);
285
322
}
286
323
287
324
// / Given a value of some non-optional actor type, convert it to
@@ -295,6 +332,13 @@ emitNonOptionalActorInstanceIsolation(SILGenFunction &SGF, SILLocation loc,
295
332
return actor;
296
333
297
334
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
+
298
342
return SGF.emitTransformExistential (loc, actor, actorType, anyActorType);
299
343
}
300
344
@@ -587,3 +631,76 @@ SILValue SILGenFunction::emitGetCurrentExecutor(SILLocation loc) {
587
631
assert (ExpectedExecutor && " prolog failed to set up expected executor?" );
588
632
return ExpectedExecutor;
589
633
}
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