33
33
34
34
using namespace swift ;
35
35
36
-
37
36
/* *****************************************************************************/
38
37
/* *********************** PROPERTY SYNTHESIS **********************************/
39
38
/* *****************************************************************************/
40
39
41
40
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
+ }
76
74
77
75
// Note: This would be nice to implement in DerivedConformanceDistributedActor,
78
76
// but we can't since those are lazily triggered and an implementation exists
@@ -83,7 +81,9 @@ lookupDistributedActorProperty(NominalTypeDecl *decl, DeclName name) {
83
81
// what already has a witness.
84
82
static VarDecl *addImplicitDistributedActorIDProperty (
85
83
ClassDecl *nominal) {
86
- if (!nominal || !nominal->isDistributedActor ())
84
+ if (!nominal)
85
+ return nullptr ;
86
+ if (!nominal->isDistributedActor ())
87
87
return nullptr ;
88
88
89
89
auto &C = nominal->getASTContext ();
@@ -131,6 +131,58 @@ static VarDecl *addImplicitDistributedActorIDProperty(
131
131
return propDecl;
132
132
}
133
133
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
+
134
186
/* *****************************************************************************/
135
187
/* ********************** DISTRIBUTED THUNK SYNTHESIS **************************/
136
188
/* *****************************************************************************/
@@ -223,6 +275,7 @@ deriveBodyDistributed_thunk(AbstractFunctionDecl *thunk, void *context) {
223
275
SmallVector<ASTNode, 8 > remoteBranchStmts;
224
276
// --- self.actorSystem
225
277
auto systemProperty = nominal->getDistributedActorSystemProperty ();
278
+ assert (systemProperty && " Unable to find 'actorSystem' property" );
226
279
auto systemRefExpr =
227
280
UnresolvedDotExpr::createImplicit (
228
281
C, new (C) DeclRefExpr (selfDecl, dloc, implicit), // TODO: make createImplicit
@@ -824,18 +877,21 @@ VarDecl *GetDistributedActorSystemPropertyRequest::evaluate(
824
877
return nullptr ;
825
878
}
826
879
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 ;
833
883
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;
836
892
}
837
893
838
- return nullptr ;
894
+ return addImplicitDistributedActorActorSystemProperty (classDecl) ;
839
895
}
840
896
841
897
NormalProtocolConformance *GetDistributedActorImplicitCodableRequest::evaluate (
0 commit comments