@@ -235,6 +235,11 @@ SILValue SILGenFunction::emitGenericExecutor(SILLocation loc) {
235
235
return B.createOptionalNone (loc, ty);
236
236
}
237
237
238
+ ManagedValue SILGenFunction::emitNonIsolatedIsolation (SILLocation loc) {
239
+ return B.createManagedOptionalNone (loc,
240
+ SILType::getOpaqueIsolationType (getASTContext ()));
241
+ }
242
+
238
243
SILValue SILGenFunction::emitLoadGlobalActorExecutor (Type globalActor) {
239
244
auto loc = RegularLocation::getAutoGeneratedLocation (F.getLocation ());
240
245
auto actor = emitLoadOfGlobalActorShared (loc, globalActor->getCanonicalType ());
@@ -268,8 +273,71 @@ SILGenFunction::emitLoadOfGlobalActorShared(SILLocation loc, CanType actorType)
268
273
return actorInstance;
269
274
}
270
275
276
+ ManagedValue
277
+ SILGenFunction::emitGlobalActorIsolation (SILLocation loc,
278
+ CanType globalActorType) {
279
+ // GlobalActor.shared returns Self, so this should be a value of
280
+ // GlobalActor type.
281
+ auto actor = emitLoadOfGlobalActorShared (loc, globalActorType);
282
+
283
+ // Since it's just a normal actor instance, we can use the normal path.
284
+ return emitActorInstanceIsolation (loc, actor, globalActorType);
285
+ }
286
+
287
+ // / Given a value of some non-optional actor type, convert it to
288
+ // / non-optional `any Actor` type.
289
+ static ManagedValue
290
+ emitNonOptionalActorInstanceIsolation (SILGenFunction &SGF, SILLocation loc,
291
+ ManagedValue actor, CanType actorType,
292
+ SILType anyActorTy) {
293
+ // If we have an `any Actor` already, we're done.
294
+ if (actor.getType () == anyActorTy)
295
+ return actor;
296
+
297
+ CanType anyActorType = anyActorTy.getASTType ();
298
+ return SGF.emitTransformExistential (loc, actor, actorType, anyActorType);
299
+ }
300
+
301
+ ManagedValue
302
+ SILGenFunction::emitActorInstanceIsolation (SILLocation loc, ManagedValue actor,
303
+ CanType actorType) {
304
+ // $Optional<any Actor>
305
+ auto optionalAnyActorTy = SILType::getOpaqueIsolationType (getASTContext ());
306
+ // Optional<any Actor> as a formal type (it's invariant to lowering)
307
+ auto optionalAnyActorType = optionalAnyActorTy.getASTType ();
308
+
309
+ // If we started with an Optional<any Actor>, we're done.
310
+ if (actorType == optionalAnyActorType) {
311
+ return actor;
312
+ }
313
+
314
+ // Otherwise, if we have an optional value, we need to transform the payload.
315
+ auto actorObjectType = actorType.getOptionalObjectType ();
316
+ if (actorObjectType) {
317
+ return emitOptionalToOptional (loc, actor, optionalAnyActorTy,
318
+ [&](SILGenFunction &SGF, SILLocation loc, ManagedValue actorObject,
319
+ SILType anyActorTy, SGFContext C) {
320
+ return emitNonOptionalActorInstanceIsolation (*this , loc, actorObject,
321
+ actorObjectType, anyActorTy);
322
+ });
323
+ }
324
+
325
+ // Otherwise, transform the non-optional value we have, then inject that
326
+ // into Optional.
327
+ SILType anyActorTy = optionalAnyActorTy.getOptionalObjectType ();
328
+ ManagedValue anyActor =
329
+ emitNonOptionalActorInstanceIsolation (*this , loc, actor, actorType,
330
+ anyActorTy);
331
+
332
+ // Inject into `Optional`.
333
+ auto result = B.createOptionalSome (loc, anyActor);
334
+ return result;
335
+ }
336
+
271
337
SILValue SILGenFunction::emitLoadActorExecutor (SILLocation loc,
272
338
ManagedValue actor) {
339
+ // FIXME: Checking for whether we're in a formal evaluation scope
340
+ // like this doesn't seem like a good pattern.
273
341
SILValue actorV;
274
342
if (isInFormalEvaluationScope ())
275
343
actorV = actor.formalAccessBorrow (*this , loc).getValue ();
@@ -291,23 +359,18 @@ SILValue SILGenFunction::emitLoadErasedExecutor(SILLocation loc,
291
359
ManagedValue
292
360
SILGenFunction::emitLoadErasedIsolation (SILLocation loc,
293
361
ManagedValue fn) {
294
- if (isInFormalEvaluationScope ())
295
- fn = fn.formalAccessBorrow (*this , loc);
296
- else
297
- fn = fn.borrow (*this , loc);
362
+ fn = fn.borrow (*this , loc);
298
363
299
364
// This expects a borrowed function and returns a borrowed (any Actor)?.
300
365
auto actor = B.createFunctionExtractIsolation (loc, fn.getValue ());
301
366
302
367
return ManagedValue::forBorrowedObjectRValue (actor);
303
368
}
304
369
305
- // / The ownership of the value returned here is mixed; callers that need
306
- // / an owned value must call ensurePlusOne.
307
370
ManagedValue
308
- SILGenFunction::emitLoadOfFunctionIsolation (SILLocation loc,
309
- FunctionTypeIsolation isolation,
310
- ManagedValue fn) {
371
+ SILGenFunction::emitFunctionTypeIsolation (SILLocation loc,
372
+ FunctionTypeIsolation isolation,
373
+ ManagedValue fn) {
311
374
switch (isolation.getKind ()) {
312
375
313
376
// Parameter-isolated functions don't have a specific actor they're isolated
@@ -318,50 +381,96 @@ SILGenFunction::emitLoadOfFunctionIsolation(SILLocation loc,
318
381
319
382
// Emit nonisolated by simply emitting Optional.none in the result type.
320
383
case FunctionTypeIsolation::Kind::NonIsolated:
321
- return B.createManagedOptionalNone (loc,
322
- SILType::getOpaqueIsolationType (getASTContext ()));
384
+ return emitNonIsolatedIsolation (loc);
323
385
324
386
// Emit global actor isolation by loading .shared from the global actor,
325
387
// erasing it into `any Actor`, and injecting that into Optional.
326
- case FunctionTypeIsolation::Kind::GlobalActor: {
327
- auto concreteActorType =
328
- isolation.getGlobalActorType ()->getCanonicalType ();
388
+ case FunctionTypeIsolation::Kind::GlobalActor:
389
+ return emitGlobalActorIsolation (loc,
390
+ isolation.getGlobalActorType ()->getCanonicalType () );
329
391
330
- // GlobalActor.shared returns Self, so this should be a value of the
331
- // actor type.
332
- auto actor = emitLoadOfGlobalActorShared (loc, concreteActorType);
392
+ // Emit @isolated(any) isolation by loading the actor reference from the
393
+ // function.
394
+ case FunctionTypeIsolation::Kind::Erased: {
395
+ Scope scope (*this , CleanupLocation (loc));
396
+ auto value = emitLoadErasedIsolation (loc, fn).copy (*this , loc);
397
+ return scope.popPreservingValue (value);
398
+ }
399
+ }
333
400
334
- auto optionalAnyActorTy = SILType::getOpaqueIsolationType (getASTContext ());
335
- auto anyActorTy = optionalAnyActorTy.getOptionalObjectType ();
336
- assert (anyActorTy);
401
+ llvm_unreachable (" bad kind" );
402
+ }
337
403
404
+ static ActorIsolation getClosureIsolationInfo (SILDeclRef constant) {
405
+ if (auto closure = constant.getAbstractClosureExpr ()) {
406
+ return closure->getActorIsolation ();
407
+ }
408
+ auto func = constant.getAbstractFunctionDecl ();
409
+ assert (func && " unexpected closure constant" );
410
+ return getActorIsolation (func);
411
+ }
338
412
339
- ArrayRef<ProtocolConformanceRef> conformances =
340
- SGM.SwiftModule ->collectExistentialConformances (concreteActorType,
341
- anyActorTy.getASTType ());
413
+ static ManagedValue emitLoadOfCaptureIsolation (SILGenFunction &SGF,
414
+ SILLocation loc,
415
+ VarDecl *isolatedCapture,
416
+ SILDeclRef constant,
417
+ ArrayRef<ManagedValue> captureArgs) {
418
+ auto &TC = SGF.SGM .Types ;
419
+ auto captureInfo = TC.getLoweredLocalCaptures (constant);
420
+
421
+ auto isolatedVarType =
422
+ isolatedCapture->getInterfaceType ()->getCanonicalType ();
423
+
424
+ // Capture arguments are 1-1 with the lowered capture info.
425
+ auto captures = captureInfo.getCaptures ();
426
+ for (auto i : indices (captures)) {
427
+ const auto &capture = captures[i];
428
+ if (capture.isDynamicSelfMetadata ()) continue ;
429
+ auto capturedVar = capture.getDecl ();
430
+ if (capturedVar != isolatedCapture) continue ;
431
+
432
+ // Captured actor references should always be captured as constants.
433
+ assert (TC.getDeclCaptureKind (capture,
434
+ TC.getCaptureTypeExpansionContext (constant))
435
+ == CaptureKind::Constant);
436
+
437
+ auto value = captureArgs[i].copy (SGF, loc);
438
+ return SGF.emitActorInstanceIsolation (loc, value, isolatedVarType);
439
+ }
342
440
343
- for (auto conf: conformances)
344
- SGM.useConformance (conf);
441
+ // The capture not being a lowered capture can happen in global code.
442
+ auto value = SGF.emitRValueForDecl (loc, isolatedCapture, isolatedVarType,
443
+ AccessSemantics::Ordinary)
444
+ .getAsSingleValue (SGF, loc);
445
+ return SGF.emitActorInstanceIsolation (loc, value, isolatedVarType);
446
+ }
345
447
346
- // Erase to `any Actor`.
347
- assert (anyActorTy.getPreferredExistentialRepresentation (concreteActorType)
348
- == ExistentialRepresentation::Class);
349
- auto erasedActor = B.createInitExistentialRef (loc, anyActorTy,
350
- concreteActorType,
351
- actor, conformances);
448
+ ManagedValue
449
+ SILGenFunction::emitClosureIsolation (SILLocation loc, SILDeclRef constant,
450
+ ArrayRef<ManagedValue> captures) {
451
+ auto isolation = getClosureIsolationInfo (constant);
452
+ switch (isolation) {
453
+ case ActorIsolation::Unspecified:
454
+ case ActorIsolation::Nonisolated:
455
+ case ActorIsolation::NonisolatedUnsafe:
456
+ return emitNonIsolatedIsolation (loc);
352
457
353
- // Inject into `Optional`.
354
- auto result = B. createOptionalSome (loc, erasedActor );
458
+ case ActorIsolation::Erased:
459
+ llvm_unreachable ( " closures cannot directly have erased isolation " );
355
460
356
- return result;
357
- }
461
+ case ActorIsolation::GlobalActor:
462
+ return emitGlobalActorIsolation (loc,
463
+ isolation.getGlobalActor ()->getCanonicalType ());
358
464
359
- // Emit @isolated(any) isolation by loading the actor reference from the
360
- // function.
361
- case FunctionTypeIsolation::Kind::Erased:
362
- return emitLoadErasedIsolation (loc, fn);
465
+ case ActorIsolation::ActorInstance: {
466
+ // This should always be a capture. That's not expressed super-cleanly
467
+ // in ActorIsolation, unfortunately.
468
+ assert (isolation.getActorInstanceParameter () == 0 );
469
+ auto capture = isolation.getActorInstance ();
470
+ assert (capture);
471
+ return emitLoadOfCaptureIsolation (*this , loc, capture, constant, captures);
472
+ }
363
473
}
364
-
365
474
llvm_unreachable (" bad kind" );
366
475
}
367
476
0 commit comments