@@ -2651,6 +2651,11 @@ namespace {
2651
2651
}
2652
2652
}
2653
2653
}
2654
+
2655
+ // / Determine whether the given reference is to a method on
2656
+ // / a remote distributed actor in the given context.
2657
+ bool isDistributedThunk (ConcreteDeclRef ref, Expr *context,
2658
+ bool isInAsyncLetInitializer);
2654
2659
};
2655
2660
}
2656
2661
@@ -2683,6 +2688,58 @@ bool ActorIsolationChecker::mayExecuteConcurrentlyWith(
2683
2688
return false ;
2684
2689
}
2685
2690
2691
+ bool ActorIsolationChecker::isDistributedThunk (ConcreteDeclRef ref,
2692
+ Expr *context,
2693
+ bool isInAsyncLetInitializer) {
2694
+ auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(ref.getDecl ());
2695
+ if (!(FD && FD->isInstanceMember () && FD->isDistributed ()))
2696
+ return false ;
2697
+
2698
+ if (!isa<SelfApplyExpr>(context))
2699
+ return false ;
2700
+
2701
+ auto actor = getIsolatedActor (cast<SelfApplyExpr>(context)->getBase ());
2702
+
2703
+ // If this is a method reference on an isolated or potentially isolated
2704
+ // actor then it cannot be a remote thunk.
2705
+ if (actor.isIsolated () || actor.isPotentiallyIsolated )
2706
+ return false ;
2707
+
2708
+ auto *dc = getDeclContext ();
2709
+
2710
+ switch (ActorIsolationRestriction::forDeclaration (ref, dc)) {
2711
+ case ActorIsolationRestriction::CrossActorSelf: {
2712
+ // Not a thunk if it's used in actor init or de-init.
2713
+ if (!isInAsyncLetInitializer && isActorInitOrDeInitContext (dc))
2714
+ return false ;
2715
+
2716
+ // Here we know that the method could be used across actors
2717
+ // and the actor it's used on is non-isolated, which means
2718
+ // that it could be a thunk, so we have to be conservative
2719
+ // about it.
2720
+ return true ;
2721
+ }
2722
+
2723
+ case ActorIsolationRestriction::ActorSelf: {
2724
+ // An instance member of an actor can be referenced from an actor's
2725
+ // designated initializer or deinitializer.
2726
+ if (actor.isActorSelf () && !isInAsyncLetInitializer) {
2727
+ if (auto fn = isActorInitOrDeInitContext (dc)) {
2728
+ if (!isConvenienceInit (fn))
2729
+ return false ;
2730
+ }
2731
+ }
2732
+
2733
+ // Call on a non-isolated actor in async context requires
2734
+ // implicit thunk.
2735
+ return isInAsyncLetInitializer || isInAsynchronousContext ();
2736
+ }
2737
+
2738
+ default :
2739
+ return false ;
2740
+ }
2741
+ }
2742
+
2686
2743
void swift::checkTopLevelActorIsolation (TopLevelCodeDecl *decl) {
2687
2744
ActorIsolationChecker checker (decl);
2688
2745
decl->getBody ()->walk (checker);
@@ -4285,3 +4342,11 @@ bool swift::isAsynchronousContext(const DeclContext *dc) {
4285
4342
4286
4343
return false ;
4287
4344
}
4345
+
4346
+ bool swift::constraints::isDistributedThunk (ConcreteDeclRef ref,
4347
+ Expr *context,
4348
+ DeclContext *dc,
4349
+ bool isInAsyncLetInitializer) {
4350
+ ActorIsolationChecker checker (dc);
4351
+ return checker.isDistributedThunk (ref, context, isInAsyncLetInitializer);
4352
+ }
0 commit comments