Skip to content

Commit 74503f0

Browse files
authored
Use the distributed thunk for non-distributed protocol requirements (#59513)
When a distributed-actor-isolated witness is provided for a non-distributed-actor-isolated requirement, always hop to the distributed thunk. While here, mark distributed thunks as being `final`, to ensure that we always statically call them vs. trying to retrieve them from the vtable (since they aren't in the vtable).
1 parent 7e84355 commit 74503f0

File tree

4 files changed

+62
-27
lines changed

4 files changed

+62
-27
lines changed

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,8 +1052,6 @@ bool SILDeclRef::requiresNewVTableEntry() const {
10521052
return true;
10531053
if (!hasDecl())
10541054
return false;
1055-
if (isDistributedThunk())
1056-
return false;
10571055
if (isBackDeploymentThunk())
10581056
return false;
10591057
auto fnDecl = dyn_cast<AbstractFunctionDecl>(getDecl());

lib/SILGen/SILGenPoly.cpp

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4434,41 +4434,45 @@ void SILGenFunction::emitProtocolWitness(
44344434
FullExpr scope(Cleanups, cleanupLoc);
44354435
FormalEvaluationScope formalEvalScope(*this);
44364436

4437-
auto witnessKind = getWitnessDispatchKind(witness, isSelfConformance);
44384437
auto thunkTy = F.getLoweredFunctionType();
44394438

44404439
SmallVector<ManagedValue, 8> origParams;
44414440
collectThunkParams(loc, origParams);
44424441

4443-
// If we are supposed to enter the actor, do so now.
4444-
if (enterIsolation) {
4445-
if (enterIsolation->isDistributedActor()) {
4446-
// For a distributed actor, call through the distributed thunk.
4447-
witness = witness.asDistributed();
4448-
} else {
4449-
// For a non-distributed actor, hop to the actor.
4450-
Optional<ManagedValue> actorSelf;
4451-
4452-
// For an instance actor, get the actor 'self'.
4453-
if (*enterIsolation == ActorIsolation::ActorInstance) {
4454-
auto actorSelfVal = origParams.back();
4455-
4456-
if (actorSelfVal.getType().isAddress()) {
4457-
auto &actorSelfTL = getTypeLowering(actorSelfVal.getType());
4458-
if (!actorSelfTL.isAddressOnly()) {
4459-
actorSelfVal = emitManagedLoad(
4460-
*this, loc, actorSelfVal, actorSelfTL);
4461-
}
4442+
// If the witness is isolated to a distributed actor, but the requirement is
4443+
// not, go through the distributed thunk.
4444+
if (witness.hasDecl() &&
4445+
getActorIsolation(witness.getDecl()).isDistributedActor() &&
4446+
requirement.hasDecl() &&
4447+
!getActorIsolation(requirement.getDecl()).isDistributedActor()) {
4448+
witness = SILDeclRef(
4449+
cast<AbstractFunctionDecl>(witness.getDecl())->getDistributedThunk())
4450+
.asDistributed();
4451+
} else if (enterIsolation) {
4452+
// If we are supposed to enter the actor, do so now by hopping to the
4453+
// actor.
4454+
Optional<ManagedValue> actorSelf;
4455+
4456+
// For an instance actor, get the actor 'self'.
4457+
if (*enterIsolation == ActorIsolation::ActorInstance) {
4458+
auto actorSelfVal = origParams.back();
4459+
4460+
if (actorSelfVal.getType().isAddress()) {
4461+
auto &actorSelfTL = getTypeLowering(actorSelfVal.getType());
4462+
if (!actorSelfTL.isAddressOnly()) {
4463+
actorSelfVal = emitManagedLoad(
4464+
*this, loc, actorSelfVal, actorSelfTL);
44624465
}
4463-
4464-
actorSelf = actorSelfVal;
44654466
}
44664467

4467-
emitHopToTargetActor(loc, enterIsolation, actorSelf);
4468+
actorSelf = actorSelfVal;
44684469
}
4470+
4471+
emitHopToTargetActor(loc, enterIsolation, actorSelf);
44694472
}
44704473

44714474
// Get the type of the witness.
4475+
auto witnessKind = getWitnessDispatchKind(witness, isSelfConformance);
44724476
auto witnessInfo = getConstantInfo(getTypeExpansionContext(), witness);
44734477
CanAnyFunctionType witnessSubstTy = witnessInfo.LoweredType;
44744478
if (auto genericFnType = dyn_cast<GenericFunctionType>(witnessSubstTy)) {

lib/Sema/CodeSynthesisDistributedActor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,10 @@ static FuncDecl *createDistributedThunkFunction(FuncDecl *func) {
699699
func->getResultInterfaceType(), DC);
700700
thunk->setSynthesized(true);
701701
thunk->getAttrs().add(new (C) NonisolatedAttr(/*isImplicit=*/true));
702+
703+
if (isa<ClassDecl>(DC))
704+
thunk->getAttrs().add(new (C) FinalAttr(/*isImplicit=*/true));
705+
702706
thunk->setGenericSignature(baseSignature);
703707
thunk->copyFormalAccessFrom(func, /*sourceIsParentContext=*/false);
704708
thunk->setBodySynthesizer(deriveBodyDistributed_thunk, func);

test/SILGen/distributed_thunk.swift

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,37 @@ protocol ServerProto {
2525
extension DA: ServerProto {
2626
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s17distributed_thunk2DACAA11ServerProtoA2aDP11doSomethingyyYaKFTW : $@convention(witness_method: ServerProto) @async (@in_guaranteed DA) -> @error Error
2727
// CHECK-NOT: hop_to_executor
28-
// CHECK-NOT: return
29-
// CHECK: function_ref @$s17distributed_thunk2DAC11doSomethingyyFTE
28+
// CHECK: function_ref @$s17distributed_thunk2DAC11doSomethingyyYaKFTE
3029
// CHECK: return
3130
distributed func doSomething() { }
3231
}
32+
33+
distributed actor DA2: ServerProto {
34+
typealias ActorSystem = LocalTestingDistributedActorSystem
35+
36+
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s17distributed_thunk3DA2CAA11ServerProtoA2aDP11doSomethingyyYaKFTW : $@convention(witness_method: ServerProto) @async (@in_guaranteed DA2) -> @error Error
37+
// CHECK-NOT: hop_to_executor
38+
// CHECK-NOT: return
39+
// CHECK: function_ref @$s17distributed_thunk3DA2C11doSomethingyyYaKFTE
40+
distributed func doSomething() async { }
41+
}
42+
43+
distributed actor DA3: ServerProto {
44+
typealias ActorSystem = LocalTestingDistributedActorSystem
45+
46+
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s17distributed_thunk3DA3CAA11ServerProtoA2aDP11doSomethingyyYaKFTW
47+
// CHECK-NOT: hop_to_executor
48+
// CHECK-NOT: return
49+
// CHECK: function_ref @$s17distributed_thunk3DA3C11doSomethingyyYaKFTE
50+
distributed func doSomething() async throws { }
51+
}
52+
53+
distributed actor DA4: ServerProto {
54+
typealias ActorSystem = LocalTestingDistributedActorSystem
55+
56+
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s17distributed_thunk3DA4CAA11ServerProtoA2aDP11doSomethingyyYaKFTW
57+
// CHECK-NOT: hop_to_executor
58+
// CHECK-NOT: return
59+
// CHECK: function_ref @$s17distributed_thunk3DA4C11doSomethingyyYaKFTE
60+
distributed func doSomething() throws { }
61+
}

0 commit comments

Comments
 (0)