Skip to content

Commit df462ea

Browse files
authored
[Distributed] Be able to synthesize actorSystem prop from request (#59460)
* [Distributed] Be able to synthesize actorSystem prop from request * [Distributed] remove duped lookupProp func, we have it in swift:: * Undo removal of method which was duped on 5.7 but is not on main
1 parent d1b2439 commit df462ea

File tree

2 files changed

+103
-47
lines changed

2 files changed

+103
-47
lines changed

lib/Sema/CodeSynthesisDistributedActor.cpp

Lines changed: 101 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -33,46 +33,44 @@
3333

3434
using namespace swift;
3535

36-
3736
/******************************************************************************/
3837
/************************ PROPERTY SYNTHESIS **********************************/
3938
/******************************************************************************/
4039

4140
static VarDecl*
42-
lookupDistributedActorProperty(NominalTypeDecl *decl, DeclName name) {
43-
assert(decl && "decl was null");
44-
auto &C = decl->getASTContext();
45-
46-
auto clazz = dyn_cast<ClassDecl>(decl);
47-
if (!clazz)
48-
return nullptr;
49-
50-
auto refs = decl->lookupDirect(name);
51-
if (refs.size() != 1)
52-
return nullptr;
53-
54-
auto var = dyn_cast<VarDecl>(refs.front());
55-
if (!var)
56-
return nullptr;
57-
58-
Type expectedType = Type();
59-
if (name == C.Id_id) {
60-
expectedType = getDistributedActorIDType(decl);
61-
} else if (name == C.Id_actorSystem) {
62-
expectedType = getDistributedActorSystemType(decl);
63-
} else {
64-
llvm_unreachable("Unexpected distributed actor property lookup!");
65-
}
66-
if (!expectedType)
67-
return nullptr;
68-
69-
if (!var->getInterfaceType()->isEqual(expectedType))
70-
return nullptr;
71-
72-
assert(var->isSynthesized() && "Expected compiler synthesized property");
73-
return var;
74-
}
75-
41+
lookupDistributedActorProperty(NominalTypeDecl *decl, DeclName name) {
42+
assert(decl && "decl was null");
43+
auto &C = decl->getASTContext();
44+
45+
auto clazz = dyn_cast<ClassDecl>(decl);
46+
if (!clazz)
47+
return nullptr;
48+
49+
auto refs = decl->lookupDirect(name);
50+
if (refs.size() != 1)
51+
return nullptr;
52+
53+
auto var = dyn_cast<VarDecl>(refs.front());
54+
if (!var)
55+
return nullptr;
56+
57+
Type expectedType = Type();
58+
if (name == C.Id_id) {
59+
expectedType = getDistributedActorIDType(decl);
60+
} else if (name == C.Id_actorSystem) {
61+
expectedType = getDistributedActorSystemType(decl);
62+
} else {
63+
llvm_unreachable("Unexpected distributed actor property lookup!");
64+
}
65+
if (!expectedType)
66+
return nullptr;
67+
68+
if (!var->getInterfaceType()->isEqual(expectedType))
69+
return nullptr;
70+
71+
assert(var->isSynthesized() && "Expected compiler synthesized property");
72+
return var;
73+
}
7674

7775
// Note: This would be nice to implement in DerivedConformanceDistributedActor,
7876
// but we can't since those are lazily triggered and an implementation exists
@@ -83,7 +81,9 @@ lookupDistributedActorProperty(NominalTypeDecl *decl, DeclName name) {
8381
// what already has a witness.
8482
static VarDecl *addImplicitDistributedActorIDProperty(
8583
ClassDecl *nominal) {
86-
if (!nominal || !nominal->isDistributedActor())
84+
if (!nominal)
85+
return nullptr;
86+
if (!nominal->isDistributedActor())
8787
return nullptr;
8888

8989
auto &C = nominal->getASTContext();
@@ -131,6 +131,58 @@ static VarDecl *addImplicitDistributedActorIDProperty(
131131
return propDecl;
132132
}
133133

134+
static VarDecl *addImplicitDistributedActorActorSystemProperty(
135+
ClassDecl *nominal) {
136+
if (!nominal)
137+
return nullptr;
138+
if (!nominal->isDistributedActor())
139+
return nullptr;
140+
141+
auto &C = nominal->getASTContext();
142+
143+
// ==== Synthesize and add 'actorSystem' property to the actor decl
144+
Type propertyType = getDistributedActorSystemType(nominal);
145+
146+
auto *propDecl = new (C)
147+
VarDecl(/*IsStatic*/false, VarDecl::Introducer::Let,
148+
SourceLoc(), C.Id_actorSystem, nominal);
149+
propDecl->setImplicit();
150+
propDecl->setSynthesized();
151+
propDecl->copyFormalAccessFrom(nominal, /*sourceIsParentContext*/ true);
152+
propDecl->setInterfaceType(propertyType);
153+
154+
Pattern *propPat = NamedPattern::createImplicit(C, propDecl);
155+
propPat->setType(propertyType);
156+
157+
propPat = TypedPattern::createImplicit(C, propPat, propertyType);
158+
propPat->setType(propertyType);
159+
160+
PatternBindingDecl *pbDecl = PatternBindingDecl::createImplicit(
161+
C, StaticSpellingKind::None, propPat, /*InitExpr*/ nullptr,
162+
nominal);
163+
164+
// mark as nonisolated, allowing access to it from everywhere
165+
propDecl->getAttrs().add(
166+
new (C) NonisolatedAttr(/*IsImplicit=*/true));
167+
168+
auto idProperty = nominal->getDistributedActorIDProperty();
169+
// If the id was not yet synthesized, we need to ensure that eventually
170+
// the order of fields will be: id, actorSystem (because IRGen needs the
171+
// layouts to match with the AST we produce). We do this by inserting FIRST,
172+
// and then as the ID gets synthesized, it'll also force FIRST and therefore
173+
// the order will be okey -- ID and then system.
174+
auto insertAtHead = idProperty == nullptr;
175+
176+
// IMPORTANT: The `id` MUST be the first field of any distributed actor.
177+
// So we find the property and add the system AFTER it using the hint.
178+
//
179+
// If the `id` was not synthesized yet, we'll end up inserting at head,
180+
// but the id synthesis will force itself to be FIRST anyway, so it works out.
181+
nominal->addMember(propDecl, /*hint=*/idProperty, /*insertAtHead=*/insertAtHead);
182+
nominal->addMember(pbDecl, /*hint=*/idProperty, /*insertAtHead=*/insertAtHead);
183+
return propDecl;
184+
}
185+
134186
/******************************************************************************/
135187
/*********************** DISTRIBUTED THUNK SYNTHESIS **************************/
136188
/******************************************************************************/
@@ -223,6 +275,7 @@ deriveBodyDistributed_thunk(AbstractFunctionDecl *thunk, void *context) {
223275
SmallVector<ASTNode, 8> remoteBranchStmts;
224276
// --- self.actorSystem
225277
auto systemProperty = nominal->getDistributedActorSystemProperty();
278+
assert(systemProperty && "Unable to find 'actorSystem' property");
226279
auto systemRefExpr =
227280
UnresolvedDotExpr::createImplicit(
228281
C, new (C) DeclRefExpr(selfDecl, dloc, implicit), // TODO: make createImplicit
@@ -824,18 +877,21 @@ VarDecl *GetDistributedActorSystemPropertyRequest::evaluate(
824877
return nullptr;
825878
}
826879

827-
for (auto system : nominal->lookupDirect(C.Id_actorSystem)) {
828-
if (auto var = dyn_cast<VarDecl>(system)) {
829-
auto conformance = module->conformsToProtocol(
830-
var->getInterfaceType(), DAS);
831-
if (conformance.isInvalid())
832-
continue;
880+
auto classDecl = dyn_cast<ClassDecl>(nominal);
881+
if (!classDecl)
882+
return nullptr;
833883

834-
return var;
835-
}
884+
// We may be triggered after synthesis was handled via `DerivedConformances`,
885+
// in which case we should locate the existing property, rather than add
886+
// another one. Generally derived conformances are triggered early and are right
887+
// but for some reason sometimes we get a request before synthesis was triggered
888+
// there... so this is to workaround that issue, and ensure we're always
889+
// synthesising correctly, regardless of entry-point.
890+
if (auto existingProp = lookupDistributedActorProperty(classDecl, C.Id_actorSystem)) {
891+
return existingProp;
836892
}
837893

838-
return nullptr;
894+
return addImplicitDistributedActorActorSystemProperty(classDecl);
839895
}
840896

841897
NormalProtocolConformance *GetDistributedActorImplicitCodableRequest::evaluate(

lib/Sema/DerivedConformances.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,11 +338,11 @@ ValueDecl *DerivedConformance::getDerivableRequirement(NominalTypeDecl *nominal,
338338
return getRequirement(KnownProtocolKind::Actor);
339339

340340
// DistributedActor.id
341-
if(name.isSimpleName(ctx.Id_id))
341+
if (name.isSimpleName(ctx.Id_id))
342342
return getRequirement(KnownProtocolKind::DistributedActor);
343343

344344
// DistributedActor.actorSystem
345-
if(name.isSimpleName(ctx.Id_actorSystem))
345+
if (name.isSimpleName(ctx.Id_actorSystem))
346346
return getRequirement(KnownProtocolKind::DistributedActor);
347347

348348
return nullptr;

0 commit comments

Comments
 (0)