@@ -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,13 +273,70 @@ 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) {
273
- SILValue actorV;
274
- if (isInFormalEvaluationScope ())
275
- actorV = actor.formalAccessBorrow (*this , loc).getValue ();
276
- else
277
- actorV = actor.borrow (*this , loc).getValue ();
339
+ SILValue actorV = actor.borrow (*this , loc).getValue ();
278
340
279
341
// For now, we just want to emit a hop_to_executor directly to the
280
342
// actor; LowerHopToActor will add the emission logic necessary later.
@@ -291,23 +353,18 @@ SILValue SILGenFunction::emitLoadErasedExecutor(SILLocation loc,
291
353
ManagedValue
292
354
SILGenFunction::emitLoadErasedIsolation (SILLocation loc,
293
355
ManagedValue fn) {
294
- if (isInFormalEvaluationScope ())
295
- fn = fn.formalAccessBorrow (*this , loc);
296
- else
297
- fn = fn.borrow (*this , loc);
356
+ fn = fn.borrow (*this , loc);
298
357
299
358
// This expects a borrowed function and returns a borrowed (any Actor)?.
300
359
auto actor = B.createFunctionExtractIsolation (loc, fn.getValue ());
301
360
302
361
return ManagedValue::forBorrowedObjectRValue (actor);
303
362
}
304
363
305
- // / The ownership of the value returned here is mixed; callers that need
306
- // / an owned value must call ensurePlusOne.
307
364
ManagedValue
308
- SILGenFunction::emitLoadOfFunctionIsolation (SILLocation loc,
309
- FunctionTypeIsolation isolation,
310
- ManagedValue fn) {
365
+ SILGenFunction::emitFunctionTypeIsolation (SILLocation loc,
366
+ FunctionTypeIsolation isolation,
367
+ ManagedValue fn) {
311
368
switch (isolation.getKind ()) {
312
369
313
370
// Parameter-isolated functions don't have a specific actor they're isolated
@@ -318,50 +375,96 @@ SILGenFunction::emitLoadOfFunctionIsolation(SILLocation loc,
318
375
319
376
// Emit nonisolated by simply emitting Optional.none in the result type.
320
377
case FunctionTypeIsolation::Kind::NonIsolated:
321
- return B.createManagedOptionalNone (loc,
322
- SILType::getOpaqueIsolationType (getASTContext ()));
378
+ return emitNonIsolatedIsolation (loc);
323
379
324
380
// Emit global actor isolation by loading .shared from the global actor,
325
381
// erasing it into `any Actor`, and injecting that into Optional.
326
- case FunctionTypeIsolation::Kind::GlobalActor: {
327
- auto concreteActorType =
328
- isolation.getGlobalActorType ()->getCanonicalType ();
382
+ case FunctionTypeIsolation::Kind::GlobalActor:
383
+ return emitGlobalActorIsolation (loc,
384
+ isolation.getGlobalActorType ()->getCanonicalType () );
329
385
330
- // GlobalActor.shared returns Self, so this should be a value of the
331
- // actor type.
332
- auto actor = emitLoadOfGlobalActorShared (loc, concreteActorType);
386
+ // Emit @isolated(any) isolation by loading the actor reference from the
387
+ // function.
388
+ case FunctionTypeIsolation::Kind::Erased: {
389
+ Scope scope (*this , CleanupLocation (loc));
390
+ auto value = emitLoadErasedIsolation (loc, fn).copy (*this , loc);
391
+ return scope.popPreservingValue (value);
392
+ }
393
+ }
333
394
334
- auto optionalAnyActorTy = SILType::getOpaqueIsolationType (getASTContext ());
335
- auto anyActorTy = optionalAnyActorTy.getOptionalObjectType ();
336
- assert (anyActorTy);
395
+ llvm_unreachable (" bad kind" );
396
+ }
337
397
398
+ static ActorIsolation getClosureIsolationInfo (SILDeclRef constant) {
399
+ if (auto closure = constant.getAbstractClosureExpr ()) {
400
+ return closure->getActorIsolation ();
401
+ }
402
+ auto func = constant.getAbstractFunctionDecl ();
403
+ assert (func && " unexpected closure constant" );
404
+ return getActorIsolation (func);
405
+ }
338
406
339
- ArrayRef<ProtocolConformanceRef> conformances =
340
- SGM.SwiftModule ->collectExistentialConformances (concreteActorType,
341
- anyActorTy.getASTType ());
407
+ static ManagedValue emitLoadOfCaptureIsolation (SILGenFunction &SGF,
408
+ SILLocation loc,
409
+ VarDecl *isolatedCapture,
410
+ SILDeclRef constant,
411
+ ArrayRef<ManagedValue> captureArgs) {
412
+ auto &TC = SGF.SGM .Types ;
413
+ auto captureInfo = TC.getLoweredLocalCaptures (constant);
414
+
415
+ auto isolatedVarType =
416
+ isolatedCapture->getInterfaceType ()->getCanonicalType ();
417
+
418
+ // Capture arguments are 1-1 with the lowered capture info.
419
+ auto captures = captureInfo.getCaptures ();
420
+ for (auto i : indices (captures)) {
421
+ const auto &capture = captures[i];
422
+ if (capture.isDynamicSelfMetadata ()) continue ;
423
+ auto capturedVar = capture.getDecl ();
424
+ if (capturedVar != isolatedCapture) continue ;
425
+
426
+ // Captured actor references should always be captured as constants.
427
+ assert (TC.getDeclCaptureKind (capture,
428
+ TC.getCaptureTypeExpansionContext (constant))
429
+ == CaptureKind::Constant);
430
+
431
+ auto value = captureArgs[i].copy (SGF, loc);
432
+ return SGF.emitActorInstanceIsolation (loc, value, isolatedVarType);
433
+ }
342
434
343
- for (auto conf: conformances)
344
- SGM.useConformance (conf);
435
+ // The capture not being a lowered capture can happen in global code.
436
+ auto value = SGF.emitRValueForDecl (loc, isolatedCapture, isolatedVarType,
437
+ AccessSemantics::Ordinary)
438
+ .getAsSingleValue (SGF, loc);
439
+ return SGF.emitActorInstanceIsolation (loc, value, isolatedVarType);
440
+ }
441
+
442
+ ManagedValue
443
+ SILGenFunction::emitClosureIsolation (SILLocation loc, SILDeclRef constant,
444
+ ArrayRef<ManagedValue> captures) {
445
+ auto isolation = getClosureIsolationInfo (constant);
446
+ switch (isolation) {
447
+ case ActorIsolation::Unspecified:
448
+ case ActorIsolation::Nonisolated:
449
+ case ActorIsolation::NonisolatedUnsafe:
450
+ return emitNonIsolatedIsolation (loc);
345
451
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);
452
+ case ActorIsolation::Erased:
453
+ llvm_unreachable (" closures cannot directly have erased isolation" );
352
454
353
- // Inject into `Optional`.
354
- auto result = B.createOptionalSome (loc, erasedActor);
455
+ case ActorIsolation::GlobalActor:
456
+ return emitGlobalActorIsolation (loc,
457
+ isolation.getGlobalActor ()->getCanonicalType ());
355
458
356
- return result;
459
+ case ActorIsolation::ActorInstance: {
460
+ // This should always be a capture. That's not expressed super-cleanly
461
+ // in ActorIsolation, unfortunately.
462
+ assert (isolation.getActorInstanceParameter () == 0 );
463
+ auto capture = isolation.getActorInstance ();
464
+ assert (capture);
465
+ return emitLoadOfCaptureIsolation (*this , loc, capture, constant, captures);
357
466
}
358
-
359
- // Emit @isolated(any) isolation by loading the actor reference from the
360
- // function.
361
- case FunctionTypeIsolation::Kind::Erased:
362
- return emitLoadErasedIsolation (loc, fn);
363
467
}
364
-
365
468
llvm_unreachable (" bad kind" );
366
469
}
367
470
0 commit comments