@@ -621,10 +621,13 @@ static Expr *constructDistributedUnownedSerialExecutor(ASTContext &ctx,
621
621
}
622
622
623
623
static std::pair<BraceStmt *, bool >
624
- deriveBodyDistributedActor_unownedExecutor (AbstractFunctionDecl *getter, void *) {
625
- // var unownedExecutor : UnownedSerialExecutor {
624
+ deriveBodyDistributedActor_localUnownedExecutor (AbstractFunctionDecl *getter, void *) {
625
+ // var localUnownedExecutor : UnownedSerialExecutor? {
626
626
// get {
627
- // return Builtin.buildDefaultActorExecutorRef(self)
627
+ // guard __isLocalActor(self) else {
628
+ // return nil
629
+ // }
630
+ // return Optional(Builtin.buildDefaultActorExecutorRef(self))
628
631
// }
629
632
// }
630
633
ASTContext &ctx = getter->getASTContext ();
@@ -641,33 +644,53 @@ deriveBodyDistributedActor_unownedExecutor(AbstractFunctionDecl *getter, void *)
641
644
Expr *selfArg = DerivedConformance::createSelfDeclRef (getter);
642
645
selfArg->setType (selfType);
643
646
647
+ // Prepare the builtin call, we'll use it after the guard, but want to take the type
648
+ // of its return type earlier, so we prepare it here.
649
+
644
650
// The builtin call gives us a Builtin.Executor.
645
651
auto builtinCall =
646
652
DerivedConformance::createBuiltinCall (ctx,
647
653
BuiltinValueKind::BuildDefaultActorExecutorRef,
648
654
{selfType}, {}, {selfArg});
649
-
650
655
// Turn that into an UnownedSerialExecutor.
651
656
auto initCall = constructDistributedUnownedSerialExecutor (ctx, builtinCall);
652
657
if (!initCall) return failure ();
653
658
654
- auto ret = new (ctx) ReturnStmt (SourceLoc (), initCall, /* implicit*/ true );
659
+ // guard __isLocalActor(self) else {
660
+ // return nil
661
+ // }
662
+ auto isLocalActorDecl = ctx.getIsLocalDistributedActor ();
663
+ DeclRefExpr *isLocalActorExpr =
664
+ new (ctx) DeclRefExpr (ConcreteDeclRef (isLocalActorDecl), DeclNameLoc (), /* implicit=*/ true ,
665
+ AccessSemantics::Ordinary,
666
+ FunctionType::get ({AnyFunctionType::Param (ctx.getAnyObjectType ())},
667
+ ctx.getBoolType ()));
668
+ Expr *selfForIsLocalArg = DerivedConformance::createSelfDeclRef (getter);
669
+ selfForIsLocalArg->setType (selfType);
670
+ auto *argListForIsLocal =
671
+ ArgumentList::forImplicitSingle (ctx, Identifier (),
672
+ ErasureExpr::create (ctx, selfForIsLocalArg, ctx.getAnyObjectType (), {}, {}));
673
+ CallExpr *isLocalActorCall = CallExpr::createImplicit (ctx, isLocalActorExpr, argListForIsLocal);
674
+ isLocalActorCall->setType (ctx.getBoolType ());
675
+ isLocalActorCall->setThrows (false );
676
+ auto returnNilIfRemoteStmt = DerivedConformance::returnNilIfFalseGuardTypeChecked (
677
+ ctx, isLocalActorCall, /* optionalWrappedType=*/ initCall->getType ());
678
+
679
+
680
+ // Finalize preparing the unowned executor for returning.
681
+ auto wrappedCall = new (ctx) InjectIntoOptionalExpr (initCall, initCall->getType ()->wrapInOptionalType ());
682
+
683
+ auto ret = new (ctx) ReturnStmt (SourceLoc (), wrappedCall, /* implicit*/ true );
655
684
656
685
auto body = BraceStmt::create (
657
- ctx, SourceLoc (), { ret }, SourceLoc (), /* implicit=*/ true );
686
+ ctx, SourceLoc (), { returnNilIfRemoteStmt, ret }, SourceLoc (), /* implicit=*/ true );
658
687
return { body, /* isTypeChecked=*/ true };
659
688
}
660
689
661
- // / Derive the declaration of DistributedActor's unownedExecutor property.
662
- static ValueDecl *deriveDistributedActor_unownedExecutor (DerivedConformance &derived) {
690
+ // / Derive the declaration of DistributedActor's localUnownedExecutor property.
691
+ static ValueDecl *deriveDistributedActor_localUnownedExecutor (DerivedConformance &derived) {
663
692
ASTContext &ctx = derived.Context ;
664
693
665
- if (auto classDecl = dyn_cast<ClassDecl>(derived.Nominal )) {
666
- if (auto existing = classDecl->getUnownedExecutorProperty ()) {
667
- return const_cast <VarDecl*>(existing);
668
- }
669
- }
670
-
671
694
// Retrieve the types and declarations we'll need to form this operation.
672
695
auto executorDecl = ctx.getUnownedSerialExecutorDecl ();
673
696
if (!executorDecl) {
@@ -676,16 +699,28 @@ static ValueDecl *deriveDistributedActor_unownedExecutor(DerivedConformance &der
676
699
return nullptr ;
677
700
}
678
701
Type executorType = executorDecl->getDeclaredInterfaceType ();
702
+ Type optionalExecutorType = executorType->wrapInOptionalType ();
703
+
704
+ if (auto classDecl = dyn_cast<ClassDecl>(derived.Nominal )) {
705
+ if (auto existing = classDecl->getLocalUnownedExecutorProperty ()) {
706
+ if (existing->getInterfaceType ()->isEqual (optionalExecutorType)) {
707
+ return const_cast <VarDecl *>(existing);
708
+ } else {
709
+ // bad type, should be diagnosed elsewhere
710
+ return nullptr ;
711
+ }
712
+ }
713
+ }
679
714
680
715
auto propertyPair = derived.declareDerivedProperty (
681
- DerivedConformance::SynthesizedIntroducer::Var, ctx.Id_unownedExecutor ,
682
- executorType, executorType ,
716
+ DerivedConformance::SynthesizedIntroducer::Var, ctx.Id_localUnownedExecutor ,
717
+ optionalExecutorType, optionalExecutorType ,
683
718
/* static*/ false , /* final*/ false );
684
719
auto property = propertyPair.first ;
685
720
property->setSynthesized (true );
686
721
property->getAttrs ().add (new (ctx) SemanticsAttr (SEMANTICS_DEFAULT_ACTOR,
687
722
SourceLoc (), SourceRange (),
688
- /* implicit*/ true ));
723
+ /* implicit*/ true ));
689
724
property->getAttrs ().add (new (ctx) NonisolatedAttr (/* IsImplicit=*/ true ));
690
725
691
726
// Make the property implicitly final.
@@ -703,8 +738,8 @@ static ValueDecl *deriveDistributedActor_unownedExecutor(DerivedConformance &der
703
738
property, asAvailableAs, ctx);
704
739
705
740
auto getter =
706
- derived.addGetterToReadOnlyDerivedProperty (property, executorType );
707
- getter->setBodySynthesizer (deriveBodyDistributedActor_unownedExecutor );
741
+ derived.addGetterToReadOnlyDerivedProperty (property, optionalExecutorType );
742
+ getter->setBodySynthesizer (deriveBodyDistributedActor_localUnownedExecutor );
708
743
709
744
// IMPORTANT: MUST BE AFTER [id, actorSystem].
710
745
if (auto id = derived.Nominal ->getDistributedActorIDProperty ()) {
@@ -747,24 +782,24 @@ static void assertRequiredSynthesizedPropertyOrder(DerivedConformance &derived,
747
782
if (auto id = Nominal->getDistributedActorIDProperty ()) {
748
783
if (auto system = Nominal->getDistributedActorSystemProperty ()) {
749
784
if (auto classDecl = dyn_cast<ClassDecl>(derived.Nominal )) {
750
- if (auto unownedExecutor = classDecl->getUnownedExecutorProperty ()) {
751
- int idIdx, actorSystemIdx, unownedExecutorIdx = 0 ;
785
+ if (auto localUnownedExecutor = classDecl->getLocalUnownedExecutorProperty ()) {
786
+ int idIdx, actorSystemIdx, localUnownedExecutorIdx = 0 ;
752
787
int idx = 0 ;
753
788
for (auto member: Nominal->getMembers ()) {
754
789
if (auto binding = dyn_cast<PatternBindingDecl>(member)) {
755
790
if (binding->getSingleVar ()->getName () == Context.Id_id ) {
756
791
idIdx = idx;
757
792
} else if (binding->getSingleVar ()->getName () == Context.Id_actorSystem ) {
758
793
actorSystemIdx = idx;
759
- } else if (binding->getSingleVar ()->getName () == Context.Id_unownedExecutor ) {
760
- unownedExecutorIdx = idx;
794
+ } else if (binding->getSingleVar ()->getName () == Context.Id_localUnownedExecutor ) {
795
+ localUnownedExecutorIdx = idx;
761
796
}
762
797
idx += 1 ;
763
798
}
764
799
}
765
- if (idIdx + actorSystemIdx + unownedExecutorIdx >= 0 + 1 + 2 ) {
800
+ if (idIdx + actorSystemIdx + localUnownedExecutorIdx >= 0 + 1 + 2 ) {
766
801
// we have found all the necessary fields, let's assert their order
767
- assert (idIdx < actorSystemIdx < unownedExecutorIdx && " order of fields MUST be exact." );
802
+ assert (idIdx < actorSystemIdx < localUnownedExecutorIdx && " order of fields MUST be exact." );
768
803
}
769
804
}
770
805
}
@@ -786,8 +821,8 @@ ValueDecl *DerivedConformance::deriveDistributedActor(ValueDecl *requirement) {
786
821
derivedValue = deriveDistributedActor_id (*this );
787
822
} else if (var->getName () == Context.Id_actorSystem ) {
788
823
derivedValue = deriveDistributedActor_actorSystem (*this );
789
- } else if (var->getName () == Context.Id_unownedExecutor ) {
790
- derivedValue = deriveDistributedActor_unownedExecutor (*this );
824
+ } else if (var->getName () == Context.Id_localUnownedExecutor ) {
825
+ derivedValue = deriveDistributedActor_localUnownedExecutor (*this );
791
826
}
792
827
793
828
assertRequiredSynthesizedPropertyOrder (*this , derivedValue);
0 commit comments