Skip to content

Commit ff83f72

Browse files
authored
Merge pull request #59459 from ktoso/pick-synth-system-from-request-also
🍒[5.7][Distributed] Be able to synthesize actorSystem prop from request
2 parents fb19120 + 3d06300 commit ff83f72

File tree

3 files changed

+72
-50
lines changed

3 files changed

+72
-50
lines changed

lib/AST/DistributedDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ using namespace swift;
6565
/********************** Distributed Actor Properties **************************/
6666
/******************************************************************************/
6767

68-
VarDecl* swift::lookupDistributedActorProperty(NominalTypeDecl *decl, DeclName name) {
68+
VarDecl*
69+
swift::lookupDistributedActorProperty(NominalTypeDecl *decl, DeclName name) {
6970
assert(decl && "decl was null");
7071
auto &C = decl->getASTContext();
7172

lib/Sema/CodeSynthesisDistributedActor.cpp

Lines changed: 68 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -33,47 +33,10 @@
3333

3434
using namespace swift;
3535

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

41-
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-
76-
7740
// Note: This would be nice to implement in DerivedConformanceDistributedActor,
7841
// but we can't since those are lazily triggered and an implementation exists
7942
// for the 'id' property because 'Identifiable.id' has an extension that impls
@@ -83,7 +46,9 @@ lookupDistributedActorProperty(NominalTypeDecl *decl, DeclName name) {
8346
// what already has a witness.
8447
static VarDecl *addImplicitDistributedActorIDProperty(
8548
ClassDecl *nominal) {
86-
if (!nominal || !nominal->isDistributedActor())
49+
if (!nominal)
50+
return nullptr;
51+
if (!nominal->isDistributedActor())
8752
return nullptr;
8853

8954
auto &C = nominal->getASTContext();
@@ -131,6 +96,58 @@ static VarDecl *addImplicitDistributedActorIDProperty(
13196
return propDecl;
13297
}
13398

99+
static VarDecl *addImplicitDistributedActorActorSystemProperty(
100+
ClassDecl *nominal) {
101+
if (!nominal)
102+
return nullptr;
103+
if (!nominal->isDistributedActor())
104+
return nullptr;
105+
106+
auto &C = nominal->getASTContext();
107+
108+
// ==== Synthesize and add 'actorSystem' property to the actor decl
109+
Type propertyType = getDistributedActorSystemType(nominal);
110+
111+
auto *propDecl = new (C)
112+
VarDecl(/*IsStatic*/false, VarDecl::Introducer::Let,
113+
SourceLoc(), C.Id_actorSystem, nominal);
114+
propDecl->setImplicit();
115+
propDecl->setSynthesized();
116+
propDecl->copyFormalAccessFrom(nominal, /*sourceIsParentContext*/ true);
117+
propDecl->setInterfaceType(propertyType);
118+
119+
Pattern *propPat = NamedPattern::createImplicit(C, propDecl);
120+
propPat->setType(propertyType);
121+
122+
propPat = TypedPattern::createImplicit(C, propPat, propertyType);
123+
propPat->setType(propertyType);
124+
125+
PatternBindingDecl *pbDecl = PatternBindingDecl::createImplicit(
126+
C, StaticSpellingKind::None, propPat, /*InitExpr*/ nullptr,
127+
nominal);
128+
129+
// mark as nonisolated, allowing access to it from everywhere
130+
propDecl->getAttrs().add(
131+
new (C) NonisolatedAttr(/*IsImplicit=*/true));
132+
133+
auto idProperty = nominal->getDistributedActorIDProperty();
134+
// If the id was not yet synthesized, we need to ensure that eventually
135+
// the order of fields will be: id, actorSystem (because IRGen needs the
136+
// layouts to match with the AST we produce). We do this by inserting FIRST,
137+
// and then as the ID gets synthesized, it'll also force FIRST and therefore
138+
// the order will be okey -- ID and then system.
139+
auto insertAtHead = idProperty == nullptr;
140+
141+
// IMPORTANT: The `id` MUST be the first field of any distributed actor.
142+
// So we find the property and add the system AFTER it using the hint.
143+
//
144+
// If the `id` was not synthesized yet, we'll end up inserting at head,
145+
// but the id synthesis will force itself to be FIRST anyway, so it works out.
146+
nominal->addMember(propDecl, /*hint=*/idProperty, /*insertAtHead=*/insertAtHead);
147+
nominal->addMember(pbDecl, /*hint=*/idProperty, /*insertAtHead=*/insertAtHead);
148+
return propDecl;
149+
}
150+
134151
/******************************************************************************/
135152
/*********************** DISTRIBUTED THUNK SYNTHESIS **************************/
136153
/******************************************************************************/
@@ -223,6 +240,7 @@ deriveBodyDistributed_thunk(AbstractFunctionDecl *thunk, void *context) {
223240
SmallVector<ASTNode, 8> remoteBranchStmts;
224241
// --- self.actorSystem
225242
auto systemProperty = nominal->getDistributedActorSystemProperty();
243+
assert(systemProperty && "Unable to find 'actorSystem' property");
226244
auto systemRefExpr =
227245
UnresolvedDotExpr::createImplicit(
228246
C, new (C) DeclRefExpr(selfDecl, dloc, implicit), // TODO: make createImplicit
@@ -824,18 +842,21 @@ VarDecl *GetDistributedActorSystemPropertyRequest::evaluate(
824842
return nullptr;
825843
}
826844

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;
845+
auto classDecl = dyn_cast<ClassDecl>(nominal);
846+
if (!classDecl)
847+
return nullptr;
833848

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

838-
return nullptr;
859+
return addImplicitDistributedActorActorSystemProperty(classDecl);
839860
}
840861

841862
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)