@@ -83,7 +83,9 @@ lookupDistributedActorProperty(NominalTypeDecl *decl, DeclName name) {
83
83
// what already has a witness.
84
84
static VarDecl *addImplicitDistributedActorIDProperty (
85
85
ClassDecl *nominal) {
86
- if (!nominal || !nominal->isDistributedActor ())
86
+ if (!nominal)
87
+ return nullptr ;
88
+ if (!nominal->isDistributedActor ())
87
89
return nullptr ;
88
90
89
91
auto &C = nominal->getASTContext ();
@@ -131,6 +133,55 @@ static VarDecl *addImplicitDistributedActorIDProperty(
131
133
return propDecl;
132
134
}
133
135
136
+ static VarDecl *addImplicitDistributedActorActorSystemProperty (
137
+ ClassDecl *nominal) {
138
+ if (!nominal)
139
+ return nullptr ;
140
+ if (!nominal->isDistributedActor ())
141
+ return nullptr ;
142
+
143
+ auto &C = nominal->getASTContext ();
144
+
145
+ // ==== Synthesize and add 'id' property to the actor decl
146
+ Type propertyType = getDistributedActorSystemType (nominal);
147
+
148
+ auto *propDecl = new (C)
149
+ VarDecl (/* IsStatic*/ false , VarDecl::Introducer::Let,
150
+ SourceLoc (), C.Id_actorSystem , nominal);
151
+ propDecl->setImplicit ();
152
+ propDecl->setSynthesized ();
153
+ propDecl->copyFormalAccessFrom (nominal, /* sourceIsParentContext*/ true );
154
+ propDecl->setInterfaceType (propertyType);
155
+
156
+ Pattern *propPat = NamedPattern::createImplicit (C, propDecl);
157
+ propPat->setType (propertyType);
158
+
159
+ propPat = TypedPattern::createImplicit (C, propPat, propertyType);
160
+ propPat->setType (propertyType);
161
+
162
+ PatternBindingDecl *pbDecl = PatternBindingDecl::createImplicit (
163
+ C, StaticSpellingKind::None, propPat, /* InitExpr*/ nullptr ,
164
+ nominal);
165
+
166
+ // mark as nonisolated, allowing access to it from everywhere
167
+ propDecl->getAttrs ().add (
168
+ new (C) NonisolatedAttr (/* IsImplicit=*/ true ));
169
+ // mark as @_compilerInitialized, since we synthesize the initializing
170
+ // assignment during SILGen.
171
+ propDecl->getAttrs ().add (
172
+ new (C) CompilerInitializedAttr (/* IsImplicit=*/ true ));
173
+
174
+ auto idProperty = nominal->getDistributedActorIDProperty ();
175
+ // IMPORTANT: The `id` MUST be the first field of any distributed actor.
176
+ // So we find the property and add the system AFTER it using the hint.
177
+ //
178
+ // If the `id` was not synthesized yet, we'll end up inserting at head,
179
+ // but the id synthesis will force itself to be FIRST anyway, so it works out.
180
+ nominal->addMember (propDecl, /* hint=*/ idProperty);
181
+ nominal->addMember (pbDecl, /* hint=*/ idProperty);
182
+ return propDecl;
183
+ }
184
+
134
185
/* *****************************************************************************/
135
186
/* ********************** DISTRIBUTED THUNK SYNTHESIS **************************/
136
187
/* *****************************************************************************/
@@ -223,6 +274,7 @@ deriveBodyDistributed_thunk(AbstractFunctionDecl *thunk, void *context) {
223
274
SmallVector<ASTNode, 8 > remoteBranchStmts;
224
275
// --- self.actorSystem
225
276
auto systemProperty = nominal->getDistributedActorSystemProperty ();
277
+ assert (systemProperty && " Unable to find 'actorSystem' property" );
226
278
auto systemRefExpr =
227
279
UnresolvedDotExpr::createImplicit (
228
280
C, new (C) DeclRefExpr (selfDecl, dloc, implicit), // TODO: make createImplicit
@@ -824,18 +876,21 @@ VarDecl *GetDistributedActorSystemPropertyRequest::evaluate(
824
876
return nullptr ;
825
877
}
826
878
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 ;
879
+ auto classDecl = dyn_cast<ClassDecl>(nominal);
880
+ if (!classDecl)
881
+ return nullptr ;
833
882
834
- return var;
835
- }
883
+ // We may be triggered after synthesis was handled via `DerivedConformances`,
884
+ // in which case we should locate the existing property, rather than add
885
+ // another one. Generally derived conformances are triggered early and are right
886
+ // but for some reason sometimes we get a request before synthesis was triggered
887
+ // there... so this is to workaround that issue, and ensure we're always
888
+ // synthesising correctly, regardless of entry-point.
889
+ if (auto existingProp = lookupDistributedActorProperty (classDecl, C.Id_actorSystem )) {
890
+ return existingProp;
836
891
}
837
892
838
- return nullptr ;
893
+ return addImplicitDistributedActorActorSystemProperty (classDecl) ;
839
894
}
840
895
841
896
NormalProtocolConformance *GetDistributedActorImplicitCodableRequest::evaluate (
0 commit comments