@@ -620,9 +620,79 @@ static Expr *constructDistributedUnownedSerialExecutor(ASTContext &ctx,
620
620
return nullptr ;
621
621
}
622
622
623
+ // static Expr *constructOptionalSome(ASTContext &ctx,
624
+ // Expr *arg) {
625
+ // auto optionalDecl = ctx.getOptionalDecl();
626
+ // if (!optionalDecl) return nullptr;
627
+ //
628
+ // for (auto member: optionalDecl->getAllMembers()) {
629
+ // auto ctor = dyn_cast<ConstructorDecl>(member);
630
+ // if (!ctor) continue;
631
+ //
632
+ // // Find the init(_:) which initialized as `some`
633
+ // auto params = ctor->getParameters();
634
+ // if (params->size() != 1 ||
635
+ // params->get(0)->getArgumentName() != Identifier())
636
+ // continue;
637
+ //
638
+ // ctor->dump();
639
+ //
640
+ //
641
+ // // Type optionalType = optionalDecl->getDeclaredInterfaceType();
642
+ // // fprintf(stderr, "[%s:%d](%s) optionalDecl\n", __FILE_NAME__, __LINE__, __FUNCTION__);
643
+ // // optionalType.dump();
644
+ //
645
+ // Type optionalType = BoundGenericEnumType::get(optionalDecl, Type(), {arg->getType()});
646
+ // fprintf(stderr, "[%s:%d](%s) better optionalType\n", __FILE_NAME__, __LINE__, __FUNCTION__);
647
+ // optionalType->dump();
648
+ //
649
+ // Type ctorType = ctor->getInterfaceType();
650
+ // fprintf(stderr, "[%s:%d](%s) ctor type\n", __FILE_NAME__, __LINE__, __FUNCTION__);
651
+ // ctorType->dump();
652
+ //
653
+ // // We have the right initializer. Build a reference to it of type:
654
+ // // (Optional.Type)
655
+ // // -> (T) -> T
656
+ // auto initRef = new (ctx) DeclRefExpr(ctor, DeclNameLoc(), /*implicit*/true,
657
+ // AccessSemantics::Ordinary,
658
+ // ctorType);
659
+ //
660
+ // // Apply the initializer to the metatype, building an expression of type:
661
+ // // (Builtin.Executor) -> Optional<UnownedSerialExecutor>
662
+ // // auto metatypeRef = TypeExpr::createImplicit(optionalType, ctx);
663
+ // auto metatypeRef = TypeExpr::createImplicit(optionalType, ctx);
664
+ // GenericIdentTypeRepr::create(ctx, DeclNameLoc(optionalDecl->getNameLoc()),
665
+ // DeclNameRef(optionalDecl->getBaseName()),
666
+ // {arg->getType()}, SourceRange());
667
+ // //
668
+ // // auto ctorAppliedType = new (ctx) TypeRepr(
669
+ // // GenericIdentTypeRepr::create(ctx, DeclNameLoc(), )
670
+ // // );
671
+ //
672
+ // // TypeExpr::createForSpecializedDecl(optionalType.get, {arg->getType()}, SourceRange(), ctx);
673
+ // // Type ctorAppliedType = ctorType->getAs<FunctionType>()->getResult();
674
+ // auto selfApply = ConstructorRefCallExpr::create(ctx, initRef, metatypeRef
675
+ // // ,
676
+ // // ctorAppliedType
677
+ // );
678
+ // selfApply->setImplicit(true);
679
+ // selfApply->setThrows(false);
680
+ //
681
+ // // Call the constructor, building an expression of type
682
+ // // Optional<T>.
683
+ // auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {arg});
684
+ // auto call = CallExpr::createImplicit(ctx, selfApply, argList);
685
+ // call->setType(optionalType);
686
+ // call->setThrows(false);
687
+ // return call;
688
+ // }
689
+ //
690
+ // assert(false);
691
+ // }
692
+
623
693
static std::pair<BraceStmt *, bool >
624
694
deriveBodyDistributedActor_unownedExecutor (AbstractFunctionDecl *getter, void *) {
625
- // var unownedExecutor: UnownedSerialExecutor {
695
+ // var unownedExecutor: UnownedSerialExecutor? {
626
696
// get {
627
697
// return Builtin.buildDefaultActorExecutorRef(self)
628
698
// }
@@ -641,33 +711,58 @@ deriveBodyDistributedActor_unownedExecutor(AbstractFunctionDecl *getter, void *)
641
711
Expr *selfArg = DerivedConformance::createSelfDeclRef (getter);
642
712
selfArg->setType (selfType);
643
713
714
+ // Prepare the builtin call, we'll use it after the guard, but want to take the type
715
+ // of its return type earlier, so we prepare it here.
716
+
644
717
// The builtin call gives us a Builtin.Executor.
645
718
auto builtinCall =
646
719
DerivedConformance::createBuiltinCall (ctx,
647
720
BuiltinValueKind::BuildDefaultActorExecutorRef,
648
721
{selfType}, {}, {selfArg});
649
-
650
722
// Turn that into an UnownedSerialExecutor.
651
723
auto initCall = constructDistributedUnownedSerialExecutor (ctx, builtinCall);
652
724
if (!initCall) return failure ();
653
725
654
- auto ret = new (ctx) ReturnStmt (SourceLoc (), initCall, /* implicit*/ true );
726
+ // guard __isLocalActor(self) else {
727
+ // return nil
728
+ // }
729
+ auto isLocalActorDecl = ctx.getIsLocalDistributedActor ();
730
+ DeclRefExpr *isLocalActorExpr =
731
+ new (ctx) DeclRefExpr (ConcreteDeclRef (isLocalActorDecl), DeclNameLoc (), /* implicit=*/ true ,
732
+ AccessSemantics::Ordinary,
733
+ FunctionType::get ({AnyFunctionType::Param (ctx.getAnyObjectType ())},
734
+ ctx.getBoolType ()));
735
+ Expr *selfForIsLocalArg = DerivedConformance::createSelfDeclRef (getter);
736
+ selfForIsLocalArg->setType (selfType);
737
+ auto *argListForIsLocal =
738
+ ArgumentList::forImplicitSingle (ctx, Identifier (),
739
+ ErasureExpr::create (ctx, selfForIsLocalArg, ctx.getAnyObjectType (), {}, {}));
740
+ CallExpr *isLocalActorCall = CallExpr::createImplicit (ctx, isLocalActorExpr, argListForIsLocal);
741
+ isLocalActorCall->setType (ctx.getBoolType ());
742
+ isLocalActorCall->setThrows (false );
743
+ auto returnNilIfRemoteStmt = DerivedConformance::returnNilIfFalseGuardTypeChecked (
744
+ ctx, isLocalActorCall, /* optionalWrappedType=*/ initCall->getType ());
745
+
746
+
747
+ // Finalize preparing the unowned executor for returning.
748
+ auto wrappedCall = new (ctx) InjectIntoOptionalExpr (initCall, initCall->getType ()->wrapInOptionalType ());
749
+
750
+ auto ret = new (ctx) ReturnStmt (SourceLoc (), wrappedCall, /* implicit*/ true );
655
751
656
752
auto body = BraceStmt::create (
657
- ctx, SourceLoc (), { ret }, SourceLoc (), /* implicit=*/ true );
753
+ ctx, SourceLoc (), { returnNilIfRemoteStmt, ret }, SourceLoc (), /* implicit=*/ true );
754
+
755
+ fprintf (stderr, " [%s:%d](%s) ================================================================================================\n " , __FILE_NAME__, __LINE__, __FUNCTION__);
756
+ body->dump ();
757
+ fprintf (stderr, " [%s:%d](%s) ================================================================================================\n " , __FILE_NAME__, __LINE__, __FUNCTION__);
758
+
658
759
return { body, /* isTypeChecked=*/ true };
659
760
}
660
761
661
762
// / Derive the declaration of DistributedActor's unownedExecutor property.
662
763
static ValueDecl *deriveDistributedActor_unownedExecutor (DerivedConformance &derived) {
663
764
ASTContext &ctx = derived.Context ;
664
765
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
766
// Retrieve the types and declarations we'll need to form this operation.
672
767
auto executorDecl = ctx.getUnownedSerialExecutorDecl ();
673
768
if (!executorDecl) {
@@ -676,16 +771,28 @@ static ValueDecl *deriveDistributedActor_unownedExecutor(DerivedConformance &der
676
771
return nullptr ;
677
772
}
678
773
Type executorType = executorDecl->getDeclaredInterfaceType ();
774
+ Type optionalExecutorType = executorType->wrapInOptionalType ();
775
+
776
+ if (auto classDecl = dyn_cast<ClassDecl>(derived.Nominal )) {
777
+ if (auto existing = classDecl->getUnownedExecutorProperty ()) {
778
+ if (existing->getInterfaceType ()->isEqual (optionalExecutorType)) {
779
+ return const_cast <VarDecl *>(existing);
780
+ } else {
781
+ // bad type, should be diagnosed elsewhere
782
+ return nullptr ;
783
+ }
784
+ }
785
+ }
679
786
680
787
auto propertyPair = derived.declareDerivedProperty (
681
788
DerivedConformance::SynthesizedIntroducer::Var, ctx.Id_unownedExecutor ,
682
- executorType, executorType ,
789
+ optionalExecutorType, optionalExecutorType ,
683
790
/* static*/ false , /* final*/ false );
684
791
auto property = propertyPair.first ;
685
792
property->setSynthesized (true );
686
793
property->getAttrs ().add (new (ctx) SemanticsAttr (SEMANTICS_DEFAULT_ACTOR,
687
794
SourceLoc (), SourceRange (),
688
- /* implicit*/ true ));
795
+ /* implicit*/ true ));
689
796
property->getAttrs ().add (new (ctx) NonisolatedAttr (/* IsImplicit=*/ true ));
690
797
691
798
// Make the property implicitly final.
@@ -703,7 +810,7 @@ static ValueDecl *deriveDistributedActor_unownedExecutor(DerivedConformance &der
703
810
property, asAvailableAs, ctx);
704
811
705
812
auto getter =
706
- derived.addGetterToReadOnlyDerivedProperty (property, executorType );
813
+ derived.addGetterToReadOnlyDerivedProperty (property, optionalExecutorType );
707
814
getter->setBodySynthesizer (deriveBodyDistributedActor_unownedExecutor);
708
815
709
816
// IMPORTANT: MUST BE AFTER [id, actorSystem].
0 commit comments