@@ -95,6 +95,65 @@ struct DenseMapInfo<swift::PartitionPrimitives::Region> {
95
95
96
96
namespace swift {
97
97
98
+ class ActorInstance {
99
+ public:
100
+ enum class Kind : uint8_t {
101
+ Value,
102
+ ActorAccessorInit = 0x1 ,
103
+ };
104
+
105
+ llvm::PointerIntPair<SILValue, 1 > value;
106
+
107
+ ActorInstance (SILValue value, Kind kind)
108
+ : value(value, std::underlying_type<Kind>::type(kind)) {}
109
+
110
+ public:
111
+ ActorInstance () : ActorInstance(SILValue(), Kind::Value) {}
112
+
113
+ static ActorInstance getForValue (SILValue value) {
114
+ return ActorInstance (value, Kind::Value);
115
+ }
116
+
117
+ static ActorInstance getForActorAccessorInit () {
118
+ return ActorInstance (SILValue (), Kind::ActorAccessorInit);
119
+ }
120
+
121
+ explicit operator bool () const { return bool (value.getOpaqueValue ()); }
122
+
123
+ Kind getKind () const { return Kind (value.getInt ()); }
124
+
125
+ SILValue getValue () const {
126
+ assert (getKind () == Kind::Value);
127
+ return value.getPointer ();
128
+ }
129
+
130
+ bool isValue () const { return getKind () == Kind::Value; }
131
+
132
+ bool isAccessorInit () const { return getKind () == Kind::ActorAccessorInit; }
133
+
134
+ bool operator ==(const ActorInstance &other) const {
135
+ // If both are null, return true.
136
+ if (!bool (*this ) && !bool (other))
137
+ return true ;
138
+
139
+ // Otherwise, check if the kinds match.
140
+ if (getKind () != other.getKind ())
141
+ return false ;
142
+
143
+ // Now that we know that the kinds match, perform the kind specific check.
144
+ switch (getKind ()) {
145
+ case Kind::Value:
146
+ return getValue () == other.getValue ();
147
+ case Kind::ActorAccessorInit:
148
+ return true ;
149
+ }
150
+ }
151
+
152
+ bool operator !=(const ActorInstance &other) const {
153
+ return !(*this == other);
154
+ }
155
+ };
156
+
98
157
class SILIsolationInfo {
99
158
public:
100
159
// / The lattice is:
@@ -122,18 +181,29 @@ class SILIsolationInfo {
122
181
123
182
// / If set this is the SILValue that represents the actor instance that we
124
183
// / derived isolatedValue from.
125
- SILValue actorInstance;
184
+ // /
185
+ // / If set to (SILValue(), 1), then we are in an
186
+ ActorInstance actorInstance;
126
187
127
- SILIsolationInfo (ActorIsolation actorIsolation , SILValue isolatedValue ,
128
- SILValue actorInstance )
188
+ SILIsolationInfo (SILValue isolatedValue , SILValue actorInstance ,
189
+ ActorIsolation actorIsolation )
129
190
: kind(Actor), actorIsolation(actorIsolation),
130
- isolatedValue (isolatedValue), actorInstance(actorInstance) {
191
+ isolatedValue (isolatedValue),
192
+ actorInstance(ActorInstance::getForValue(actorInstance)) {
131
193
assert ((!actorInstance ||
132
194
(actorIsolation.getKind () == ActorIsolation::ActorInstance &&
133
195
actorInstance->getType ().isAnyActor ())) &&
134
196
" actorInstance must be an actor if it is non-empty" );
135
197
}
136
198
199
+ SILIsolationInfo (SILValue isolatedValue, ActorInstance actorInstance,
200
+ ActorIsolation actorIsolation)
201
+ : kind(Actor), actorIsolation(actorIsolation),
202
+ isolatedValue(isolatedValue), actorInstance(actorInstance) {
203
+ assert (actorInstance);
204
+ assert (actorIsolation.getKind () == ActorIsolation::ActorInstance);
205
+ }
206
+
137
207
SILIsolationInfo (Kind kind, SILValue isolatedValue)
138
208
: kind(kind), actorIsolation(), isolatedValue(isolatedValue) {}
139
209
@@ -180,7 +250,7 @@ class SILIsolationInfo {
180
250
181
251
// / Return the specific SILValue for the actor that our isolated value is
182
252
// / isolated to if one exists.
183
- SILValue getActorInstance () const {
253
+ ActorInstance getActorInstance () const {
184
254
assert (kind == Actor);
185
255
return actorInstance;
186
256
}
@@ -193,37 +263,91 @@ class SILIsolationInfo {
193
263
194
264
[[nodiscard]] SILIsolationInfo merge (SILIsolationInfo other) const ;
195
265
196
- SILIsolationInfo withActorIsolated (SILValue isolatedValue,
197
- SILValue actorInstance,
198
- ActorIsolation isolation) {
199
- return SILIsolationInfo::getActorIsolated (isolatedValue, actorInstance,
200
- isolation);
201
- }
202
-
203
266
static SILIsolationInfo getDisconnected () { return {Kind::Disconnected}; }
204
267
205
- static SILIsolationInfo getActorIsolated (SILValue isolatedValue,
206
- SILValue actorInstance,
207
- ActorIsolation actorIsolation) {
208
- return {actorIsolation, isolatedValue, actorInstance};
209
- }
210
-
211
- static SILIsolationInfo getActorIsolated (SILValue isolatedValue,
212
- SILValue actorInstance,
213
- NominalTypeDecl *typeDecl) {
214
- if (typeDecl->isAnyActor ())
215
- return {ActorIsolation::forActorInstanceSelf (typeDecl), isolatedValue,
216
- actorInstance};
217
- auto isolation = swift::getActorIsolation (typeDecl);
218
- if (isolation.isGlobalActor ())
219
- return {isolation, isolatedValue, actorInstance};
268
+ // / Create an actor isolation for a value that we know is actor isolated to a
269
+ // / specific actor, but we do not know the specific instance yet.
270
+ // /
271
+ // / This can occur when closing over a closure with an isolated parameter or
272
+ // / if we are determining isolation of a function_ref that takes an isolated
273
+ // / parameter. In both cases, we cannot know what the actual isolation is
274
+ // / until we invoke the closure or function.
275
+ // /
276
+ // / TODO: This is just a stub currently until I implement the flow sensitive
277
+ // / part. We just treat all instances the same. There are tests that validate
278
+ // / this behavior.
279
+ static SILIsolationInfo
280
+ getFlowSensitiveActorIsolated (SILValue isolatedValue,
281
+ ActorIsolation actorIsolation) {
282
+ return {isolatedValue, SILValue (), actorIsolation};
283
+ }
284
+
285
+ // / Only use this as a fallback if we cannot find better information.
286
+ static SILIsolationInfo
287
+ getWithIsolationCrossing (ApplyIsolationCrossing crossing) {
288
+ if (crossing.getCalleeIsolation ().isActorIsolated ()) {
289
+ // SIL level, just let it through
290
+ return SILIsolationInfo (SILValue (), SILValue (),
291
+ crossing.getCalleeIsolation ());
292
+ }
293
+
220
294
return {};
221
295
}
222
296
297
+ static SILIsolationInfo getActorInstanceIsolated (SILValue isolatedValue,
298
+ SILValue actorInstance,
299
+ NominalTypeDecl *typeDecl) {
300
+ assert (actorInstance);
301
+ if (!typeDecl->isAnyActor ()) {
302
+ assert (!swift::getActorIsolation (typeDecl).isGlobalActor () &&
303
+ " Should have called getGlobalActorIsolated" );
304
+ return {};
305
+ }
306
+ return {isolatedValue, actorInstance,
307
+ ActorIsolation::forActorInstanceSelf (typeDecl)};
308
+ }
309
+
310
+ static SILIsolationInfo getActorInstanceIsolated (SILValue isolatedValue,
311
+ ActorInstance actorInstance,
312
+ NominalTypeDecl *typeDecl) {
313
+ assert (actorInstance);
314
+ if (!typeDecl->isAnyActor ()) {
315
+ assert (!swift::getActorIsolation (typeDecl).isGlobalActor () &&
316
+ " Should have called getGlobalActorIsolated" );
317
+ return {};
318
+ }
319
+ return {isolatedValue, actorInstance,
320
+ ActorIsolation::forActorInstanceSelf (typeDecl)};
321
+ }
322
+
323
+ // / A special actor instance isolated for partial apply cases where we do not
324
+ // / close over the isolated parameter and thus do not know the actual actor
325
+ // / instance that we are going to use.
326
+ static SILIsolationInfo
327
+ getPartialApplyActorInstanceIsolated (SILValue isolatedValue,
328
+ NominalTypeDecl *typeDecl) {
329
+ if (!typeDecl->isAnyActor ()) {
330
+ assert (!swift::getActorIsolation (typeDecl).isGlobalActor () &&
331
+ " Should have called getGlobalActorIsolated" );
332
+ return {};
333
+ }
334
+ return {isolatedValue, SILValue (),
335
+ ActorIsolation::forActorInstanceSelf (typeDecl)};
336
+ }
337
+
223
338
static SILIsolationInfo getGlobalActorIsolated (SILValue value,
224
339
Type globalActorType) {
225
- return getActorIsolated (value, SILValue () /* no actor instance*/ ,
226
- ActorIsolation::forGlobalActor (globalActorType));
340
+ return {value, SILValue () /* no actor instance*/ ,
341
+ ActorIsolation::forGlobalActor (globalActorType)};
342
+ }
343
+
344
+ static SILIsolationInfo getGlobalActorIsolated (SILValue value,
345
+ ValueDecl *decl) {
346
+ auto isolation = swift::getActorIsolation (decl);
347
+ if (!isolation.isGlobalActor ())
348
+ return {};
349
+ return SILIsolationInfo::getGlobalActorIsolated (value,
350
+ isolation.getGlobalActor ());
227
351
}
228
352
229
353
static SILIsolationInfo getTaskIsolated (SILValue value) {
@@ -244,6 +368,18 @@ class SILIsolationInfo {
244
368
return {};
245
369
}
246
370
371
+ // / A helper that is used to ensure that we treat certain builtin values as
372
+ // / non-Sendable that the AST level otherwise thinks are non-Sendable.
373
+ // /
374
+ // / E.x.: Builtin.RawPointer and Builtin.NativeObject
375
+ // /
376
+ // / TODO: Fix the type checker.
377
+ static bool isNonSendableType (SILType type, SILFunction *fn);
378
+
379
+ static bool isNonSendableType (SILValue value) {
380
+ return isNonSendableType (value->getType (), value->getFunction ());
381
+ }
382
+
247
383
bool hasSameIsolation (ActorIsolation actorIsolation) const ;
248
384
249
385
// / Returns true if \p this and \p other have the same isolation. It allows
0 commit comments