Skip to content

Commit 143d8f9

Browse files
ktosoxedin
andauthored
[Distributed] Handle distributed thunk requirements/witnesses (swiftlang#72151)
Co-authored-by: Pavel Yaskevich <[email protected]>
1 parent 990c870 commit 143d8f9

14 files changed

+79
-61
lines changed

include/swift/SIL/SILWitnessVisitor.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,12 @@ template <class T> class SILWitnessVisitor : public ASTVisitor<T> {
146146

147147
void visitFuncDecl(FuncDecl *func) {
148148
assert(!isa<AccessorDecl>(func));
149-
if (func->requiresNewWitnessTableEntry()) {
150-
asDerived().addMethod(SILDeclRef(func, SILDeclRef::Kind::Func));
151-
addAutoDiffDerivativeMethodsIfRequired(func, SILDeclRef::Kind::Func);
152-
addDistributedWitnessMethodsIfRequired(func, SILDeclRef::Kind::Func);
153-
}
149+
if (!func->requiresNewWitnessTableEntry())
150+
return;
151+
152+
asDerived().addMethod(SILDeclRef(func, SILDeclRef::Kind::Func));
153+
addAutoDiffDerivativeMethodsIfRequired(func, SILDeclRef::Kind::Func);
154+
addDistributedWitnessMethodsIfRequired(func, SILDeclRef::Kind::Func);
154155
}
155156

156157
void visitMissingMemberDecl(MissingMemberDecl *placeholder) {
@@ -160,7 +161,7 @@ template <class T> class SILWitnessVisitor : public ASTVisitor<T> {
160161
void visitAssociatedTypeDecl(AssociatedTypeDecl *td) {
161162
// We already visited these in the first pass.
162163
}
163-
164+
164165
void visitTypeAliasDecl(TypeAliasDecl *tad) {
165166
// We don't care about these by themselves for witnesses.
166167
}
@@ -200,11 +201,11 @@ template <class T> class SILWitnessVisitor : public ASTVisitor<T> {
200201

201202
void addDistributedWitnessMethodsIfRequired(AbstractFunctionDecl *AFD,
202203
SILDeclRef::Kind kind) {
203-
if (!AFD->isDistributed())
204+
if (!AFD || !AFD->isDistributed())
204205
return;
205206

206-
// Add another which will be witnessed by the 'distributed thunk'
207-
SILDeclRef declRef(AFD, kind);
207+
auto thunk = AFD->getDistributedThunk();
208+
SILDeclRef declRef(thunk, kind);
208209
asDerived().addMethod(declRef.asDistributed());
209210
}
210211
};

lib/AST/DistributedDecl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,9 @@ FuncDecl *AbstractStorageDecl::getDistributedThunk() const {
13461346

13471347
FuncDecl*
13481348
AbstractFunctionDecl::getDistributedThunk() const {
1349+
if (isDistributedThunk())
1350+
return const_cast<FuncDecl *>(dyn_cast<FuncDecl>(this));
1351+
13491352
if (!isDistributed())
13501353
return nullptr;
13511354

lib/AST/ProtocolConformance.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,13 @@ void NormalProtocolConformance::setWitness(ValueDecl *requirement,
686686
"requirement in wrong protocol");
687687
assert(Mapping.count(requirement) == 0 && "Witness already known");
688688
assert((!isComplete() || isInvalid() ||
689+
// TODO(distributed): properly handle isComplete() for distributed
690+
// funcs; there seems to be a problem that we mark completed, but
691+
// afterwards will record the thunk witness;
692+
(dyn_cast<FuncDecl>(requirement)
693+
? (dyn_cast<FuncDecl>(requirement)->isDistributed() ||
694+
dyn_cast<FuncDecl>(requirement)->isDistributedThunk())
695+
: false) ||
689696
requirement->getAttrs().hasAttribute<OptionalAttr>() ||
690697
requirement->getAttrs().isUnavailable(
691698
requirement->getASTContext())) &&

lib/IRGen/GenMeta.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -918,8 +918,10 @@ namespace {
918918

919919
{
920920
auto *requirement = cast<AbstractFunctionDecl>(func.getDecl());
921-
if (requirement->isDistributed())
921+
if (requirement->isDistributedThunk()) {
922+
// when thunk, because in protocol we want accessof for the thunk
922923
IGM.emitDistributedTargetAccessor(requirement);
924+
}
923925
}
924926

925927
// Classify the function.

lib/IRGen/GenProto.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2464,6 +2464,7 @@ static void addWTableTypeMetadata(IRGenModule &IGM,
24642464

24652465
auto mw = entry.getMethodWitness();
24662466
auto member = mw.Requirement;
2467+
24672468
auto &fnProtoInfo =
24682469
IGM.getProtocolInfo(conf->getProtocol(), ProtocolInfoKind::Full);
24692470
auto index = fnProtoInfo.getFunctionIndex(member).forProtocolWitnessTable();

lib/SILGen/SILGenApply.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -685,8 +685,10 @@ class Callee {
685685
if (func->isDistributed() && isa<ProtocolDecl>(func->getDeclContext())) {
686686
// If we're calling cross-actor, we must always use a distributed thunk
687687
if (!isSameActorIsolated(func, SGF.FunctionDC)) {
688-
// We must adjust the constant to use a distributed thunk.
689-
constant = constant->asDistributed();
688+
// the protocol witness must always be a distributed thunk, as we
689+
// may be crossing a remote boundary here.
690+
auto thunk = func->getDistributedThunk();
691+
constant = SILDeclRef(thunk).asDistributed();
690692
}
691693
}
692694
}

lib/SILGen/SILGenThunk.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ void SILGenModule::emitDistributedThunkForDecl(
120120
if (!thunkDecl)
121121
return;
122122

123-
if (thunkDecl->isBodySkipped())
123+
if (!thunkDecl->hasBody() || thunkDecl->isBodySkipped())
124124
return;
125125

126126
auto thunk = SILDeclRef(thunkDecl).asDistributed();

lib/Sema/CodeSynthesisDistributedActor.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -724,13 +724,6 @@ static FuncDecl *createDistributedThunkFunction(FuncDecl *func) {
724724
auto &C = func->getASTContext();
725725
auto DC = func->getDeclContext();
726726

727-
// NOTE: So we don't need a thunk in the protocol, we should call the
728-
// underlying thing instead, which MUST have a thunk, since it must be a
729-
// distributed func as well...
730-
if (isa<ProtocolDecl>(DC)) {
731-
return nullptr;
732-
}
733-
734727
DeclName thunkName;
735728

736729
// Since accessors don't have names, let's generate one based on
@@ -754,7 +747,9 @@ static FuncDecl *createDistributedThunkFunction(FuncDecl *func) {
754747
thunk->getAttrs().add(
755748
new (C) NonisolatedAttr(/*unsafe=*/false, /*implicit=*/true));
756749

757-
thunk->setBodySynthesizer(deriveBodyDistributed_thunk, func);
750+
// Protocol requirements don't have bodies.
751+
if (func->hasBody())
752+
thunk->setBodySynthesizer(deriveBodyDistributed_thunk, func);
758753

759754
/// Record which function this is a thunk for, we'll need this to link back
760755
/// calls in case this is a distributed requirement witness.
@@ -874,6 +869,10 @@ void swift::assertRequiredSynthesizedPropertyOrder(ASTContext &Context,
874869
}
875870

876871
static bool canSynthesizeDistributedThunk(AbstractFunctionDecl *distributedTarget) {
872+
// `distributed` protocol requirements are allowed without additional checks.
873+
if (isa<ProtocolDecl>(distributedTarget->getDeclContext()))
874+
return true;
875+
877876
if (getConcreteReplacementForProtocolActorSystemType(distributedTarget)) {
878877
return true;
879878
}

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,12 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current,
563563
if (!currentFile)
564564
return std::make_tuple<>();
565565

566+
if (auto func = dyn_cast<AbstractFunctionDecl>(current)) {
567+
if (func->isDistributedThunk()) {
568+
return std::make_tuple<>();
569+
}
570+
}
571+
566572
auto &ctx = current->getASTContext();
567573

568574
// Find other potential definitions.

lib/Sema/TypeCheckDistributed.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,9 @@ bool swift::checkDistributedActorSystem(const NominalTypeDecl *system) {
499499
/// \returns \c true if there was a problem with adding the attribute, \c false
500500
/// otherwise.
501501
bool swift::checkDistributedFunction(AbstractFunctionDecl *func) {
502+
if (!func->isDistributed())
503+
return false;
504+
502505
auto &C = func->getASTContext();
503506
return evaluateOrDefault(C.evaluator,
504507
CheckDistributedFunctionRequest{func},
@@ -521,6 +524,11 @@ bool CheckDistributedFunctionRequest::evaluate(
521524
if (!C.getLoadedModule(C.Id_Distributed))
522525
return true;
523526

527+
// // No checking for protocol requirements because they are not required
528+
// // to have `SerializationRequirement`.
529+
// if (isa<ProtocolDecl>(func->getDeclContext()))
530+
// return false;
531+
524532
Type serializationReqType =
525533
getDistributedActorSerializationType(func->getDeclContext());
526534

@@ -736,9 +744,6 @@ void TypeChecker::checkDistributedActor(SourceFile *SF, NominalTypeDecl *nominal
736744
}
737745

738746
bool TypeChecker::checkDistributedFunc(FuncDecl *func) {
739-
if (!func->isDistributed())
740-
return false;
741-
742747
return swift::checkDistributedFunction(func);
743748
}
744749

0 commit comments

Comments
 (0)