Skip to content

Commit 214b1bd

Browse files
committed
Add support for distributed functions in extensions of distributed actors.
Fix a few minor issues in the type checker and SILGen to properly cope with distributed functions defined within extensions of distributed actors. While here, centralize the logic that adds the "_remote_" function. Fixes rdar://84325525.
1 parent 7d7ec9e commit 214b1bd

File tree

6 files changed

+43
-55
lines changed

6 files changed

+43
-55
lines changed

lib/SILGen/SILGen.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,7 @@ static void emitOrDelayFunction(SILGenModule &SGM,
11441144
auto linkage = constant.getLinkage(ForDefinition);
11451145
bool mayDelay = !forceEmission &&
11461146
(constant.isImplicit() &&
1147+
!constant.isDynamicallyReplaceable() &&
11471148
!isPossiblyUsedExternally(linkage, SGM.M.isWholeModule()));
11481149

11491150
// Avoid emitting a delayable definition if it hasn't already been referenced.

lib/SILGen/SILGenDistributed.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -951,8 +951,20 @@ void SILGenFunction::emitDistributedThunk(SILDeclRef thunk) {
951951
auto nativeFnSILTy = SILType::getPrimitiveObjectType(nativeMethodTy);
952952
auto nativeSilFnType = nativeFnSILTy.castTo<SILFunctionType>();
953953

954-
SILValue nativeFn = emitClassMethodRef(
954+
bool isClassMethod = false;
955+
if (auto classDecl = dyn_cast<ClassDecl>(fd->getDeclContext())) {
956+
if (!classDecl->isFinal() && !fd->isFinal() &&
957+
!fd->hasForcedStaticDispatch())
958+
isClassMethod = true;
959+
}
960+
961+
SILValue nativeFn;
962+
if (isClassMethod) {
963+
nativeFn = emitClassMethodRef(
955964
loc, params[params.size() - 1], native, nativeMethodTy);
965+
} else {
966+
nativeFn = emitGlobalFunctionRef(loc, native);
967+
}
956968
auto subs = F.getForwardingSubstitutionMap();
957969

958970
if (nativeSilFnType->hasErrorResult()) {

lib/Sema/CodeSynthesisDistributedActor.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -137,24 +137,23 @@ static Identifier makeRemoteFuncIdentifier(FuncDecl* distributedFunc) {
137137
///
138138
/// and is intended to be replaced by a transport library by providing an
139139
/// appropriate @_dynamicReplacement function.
140-
AbstractFunctionDecl *TypeChecker::addImplicitDistributedActorRemoteFunction(
141-
ClassDecl *decl, AbstractFunctionDecl *AFD) {
142-
if (!decl->isDistributedActor())
140+
static AbstractFunctionDecl *addImplicitDistributedActorRemoteFunction(
141+
DeclContext *parentDC, AbstractFunctionDecl *AFD) {
142+
auto nominal = parentDC->getSelfNominalTypeDecl();
143+
if (!nominal || !nominal->isDistributedActor())
143144
return nullptr;
144145

145146
auto func = dyn_cast<FuncDecl>(AFD);
146147
if (!func || !func->isDistributed())
147148
return nullptr;
148149

149150
// ==== if the remote func already exists, return it
150-
if (auto existing = decl->lookupDirectRemoteFunc(func))
151+
if (auto existing = nominal->lookupDirectRemoteFunc(func))
151152
return existing;
152153

153154
// ==== Synthesize and add 'remote' func to the actor decl
154155

155-
auto &C = decl->getASTContext();
156-
auto parentDC = decl;
157-
156+
auto &C = func->getASTContext();
158157
auto remoteFuncIdent = makeRemoteFuncIdentifier(func);
159158

160159
auto params = ParameterList::clone(C, func->getParameters());
@@ -189,7 +188,24 @@ AbstractFunctionDecl *TypeChecker::addImplicitDistributedActorRemoteFunction(
189188
// same access control as the original function is fine
190189
remoteFuncDecl->copyFormalAccessFrom(func, /*sourceIsParentContext=*/false);
191190

192-
decl->addMember(remoteFuncDecl);
191+
cast<IterableDeclContext>(parentDC->getAsDecl())->addMember(remoteFuncDecl);
193192

194193
return remoteFuncDecl;
195194
}
195+
196+
AbstractFunctionDecl *GetDistributedRemoteFuncRequest::evaluate(
197+
Evaluator &evaluator, AbstractFunctionDecl *func) const {
198+
199+
if (!func->isDistributed())
200+
return nullptr;
201+
202+
auto &C = func->getASTContext();
203+
DeclContext *DC = func->getDeclContext();
204+
205+
// not via `ensureDistributedModuleLoaded` to avoid generating a warning,
206+
// we won't be emitting the offending decl after all.
207+
if (!C.getLoadedModule(C.Id_Distributed))
208+
return nullptr;
209+
210+
return addImplicitDistributedActorRemoteFunction(DC, func);
211+
}

lib/Sema/TypeCheckDecl.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2820,10 +2820,11 @@ static ArrayRef<Decl *> evaluateMembersRequest(
28202820
(void) var->getPropertyWrapperAuxiliaryVariables();
28212821
(void) var->getPropertyWrapperInitializerInfo();
28222822
}
2823+
}
28232824

2824-
if (auto *func = dyn_cast<FuncDecl>(member)) {
2825-
(void) func->getDistributedActorRemoteFuncDecl();
2826-
}
2825+
// For a distributed function, add the remote function.
2826+
if (auto *func = dyn_cast<FuncDecl>(member)) {
2827+
(void) func->getDistributedActorRemoteFuncDecl();
28272828
}
28282829
}
28292830

lib/Sema/TypeCheckDistributed.cpp

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -71,36 +71,6 @@ bool IsDistributedActorRequest::evaluate(
7171
return classDecl->isExplicitDistributedActor();
7272
}
7373

74-
AbstractFunctionDecl *GetDistributedRemoteFuncRequest::evaluate(
75-
Evaluator &evaluator, AbstractFunctionDecl *func) const {
76-
77-
if (!func->isDistributed())
78-
return nullptr;
79-
80-
auto &C = func->getASTContext();
81-
DeclContext *DC = func->getDeclContext();
82-
83-
// not via `ensureDistributedModuleLoaded` to avoid generating a warning,
84-
// we won't be emitting the offending decl after all.
85-
if (!C.getLoadedModule(C.Id_Distributed))
86-
return nullptr;
87-
88-
// Locate the actor decl that the member must be synthesized to.
89-
// TODO(distributed): should this just be added to the extension instead when we're in one?
90-
ClassDecl *decl = dyn_cast<ClassDecl>(DC);
91-
if (!decl) {
92-
if (auto ED = dyn_cast<ExtensionDecl>(DC)) {
93-
decl = dyn_cast<ClassDecl>(ED->getExtendedNominal());
94-
}
95-
}
96-
97-
/// A distributed func cannot be added to a non-distributed actor;
98-
/// If the 'decl' was not a distributed actor we must have declared and
99-
/// requested it from a illegal context, let's just ignore the synthesis.
100-
assert(decl && "Can't find actor detect to add implicit _remote function to");
101-
return TypeChecker::addImplicitDistributedActorRemoteFunction(decl, func);
102-
}
103-
10474
// ==== ------------------------------------------------------------------------
10575

10676
/// Check whether the function is a proper distributed function
@@ -150,7 +120,7 @@ bool swift::checkDistributedFunction(FuncDecl *func, bool diagnose) {
150120
}
151121

152122
// === Check _remote functions
153-
ClassDecl *actorDecl = dyn_cast<ClassDecl>(func->getParent());
123+
auto actorDecl = func->getParent()->getSelfNominalTypeDecl();
154124
assert(actorDecl && actorDecl->isDistributedActor());
155125

156126
// _remote function for a distributed function must not be implemented by end-users,
@@ -252,10 +222,6 @@ void TypeChecker::checkDistributedActor(ClassDecl *decl) {
252222
// --- Check all constructors
253223
if (auto ctor = dyn_cast<ConstructorDecl>(member))
254224
checkDistributedActorConstructor(decl, ctor);
255-
256-
// --- synthesize _remote functions for distributed functions
257-
if (auto func = dyn_cast<FuncDecl>(member))
258-
(void)addImplicitDistributedActorRemoteFunction(decl, func);
259225
}
260226

261227
// ==== Properties

lib/Sema/TypeChecker.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -499,14 +499,6 @@ bool checkContextualRequirements(GenericTypeDecl *decl,
499499
/// struct, class or actor.
500500
void addImplicitConstructors(NominalTypeDecl *typeDecl);
501501

502-
/// Synthesize and add a '_remote' counterpart of the passed in `func` to `decl`.
503-
///
504-
/// \param decl the actor type to add the '_remote' definition to
505-
/// \param func the 'distributed func' that the '_remote' func should mirror
506-
/// \return the synthesized function
507-
AbstractFunctionDecl *addImplicitDistributedActorRemoteFunction(
508-
ClassDecl* decl, AbstractFunctionDecl *func);
509-
510502
/// Fold the given sequence expression into an (unchecked) expression
511503
/// tree.
512504
Expr *foldSequence(SequenceExpr *expr, DeclContext *dc);

0 commit comments

Comments
 (0)