33
33
34
34
using namespace swift ;
35
35
36
-
37
36
/* *****************************************************************************/
38
37
/* *********************** PROPERTY SYNTHESIS **********************************/
39
38
/* *****************************************************************************/
40
39
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
-
77
40
// Note: This would be nice to implement in DerivedConformanceDistributedActor,
78
41
// but we can't since those are lazily triggered and an implementation exists
79
42
// for the 'id' property because 'Identifiable.id' has an extension that impls
@@ -83,7 +46,9 @@ lookupDistributedActorProperty(NominalTypeDecl *decl, DeclName name) {
83
46
// what already has a witness.
84
47
static VarDecl *addImplicitDistributedActorIDProperty (
85
48
ClassDecl *nominal) {
86
- if (!nominal || !nominal->isDistributedActor ())
49
+ if (!nominal)
50
+ return nullptr ;
51
+ if (!nominal->isDistributedActor ())
87
52
return nullptr ;
88
53
89
54
auto &C = nominal->getASTContext ();
@@ -131,6 +96,58 @@ static VarDecl *addImplicitDistributedActorIDProperty(
131
96
return propDecl;
132
97
}
133
98
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
+
134
151
/* *****************************************************************************/
135
152
/* ********************** DISTRIBUTED THUNK SYNTHESIS **************************/
136
153
/* *****************************************************************************/
@@ -223,6 +240,7 @@ deriveBodyDistributed_thunk(AbstractFunctionDecl *thunk, void *context) {
223
240
SmallVector<ASTNode, 8 > remoteBranchStmts;
224
241
// --- self.actorSystem
225
242
auto systemProperty = nominal->getDistributedActorSystemProperty ();
243
+ assert (systemProperty && " Unable to find 'actorSystem' property" );
226
244
auto systemRefExpr =
227
245
UnresolvedDotExpr::createImplicit (
228
246
C, new (C) DeclRefExpr (selfDecl, dloc, implicit), // TODO: make createImplicit
@@ -824,18 +842,21 @@ VarDecl *GetDistributedActorSystemPropertyRequest::evaluate(
824
842
return nullptr ;
825
843
}
826
844
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 ;
833
848
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;
836
857
}
837
858
838
- return nullptr ;
859
+ return addImplicitDistributedActorActorSystemProperty (classDecl) ;
839
860
}
840
861
841
862
NormalProtocolConformance *GetDistributedActorImplicitCodableRequest::evaluate (
0 commit comments