@@ -235,6 +235,11 @@ SILValue SILGenFunction::emitGenericExecutor(SILLocation loc) {
235235 return B.createOptionalNone (loc, ty);
236236}
237237
238+ ManagedValue SILGenFunction::emitNonIsolatedIsolation (SILLocation loc) {
239+ return B.createManagedOptionalNone (loc,
240+ SILType::getOpaqueIsolationType (getASTContext ()));
241+ }
242+
238243SILValue SILGenFunction::emitLoadGlobalActorExecutor (Type globalActor) {
239244 auto loc = RegularLocation::getAutoGeneratedLocation (F.getLocation ());
240245 auto actor = emitLoadOfGlobalActorShared (loc, globalActor->getCanonicalType ());
@@ -268,8 +273,71 @@ SILGenFunction::emitLoadOfGlobalActorShared(SILLocation loc, CanType actorType)
268273 return actorInstance;
269274}
270275
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+
271337SILValue SILGenFunction::emitLoadActorExecutor (SILLocation loc,
272338 ManagedValue actor) {
339+ // FIXME: Checking for whether we're in a formal evaluation scope
340+ // like this doesn't seem like a good pattern.
273341 SILValue actorV;
274342 if (isInFormalEvaluationScope ())
275343 actorV = actor.formalAccessBorrow (*this , loc).getValue ();
@@ -291,23 +359,18 @@ SILValue SILGenFunction::emitLoadErasedExecutor(SILLocation loc,
291359ManagedValue
292360SILGenFunction::emitLoadErasedIsolation (SILLocation loc,
293361 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);
298363
299364 // This expects a borrowed function and returns a borrowed (any Actor)?.
300365 auto actor = B.createFunctionExtractIsolation (loc, fn.getValue ());
301366
302367 return ManagedValue::forBorrowedObjectRValue (actor);
303368}
304369
305- // / The ownership of the value returned here is mixed; callers that need
306- // / an owned value must call ensurePlusOne.
307370ManagedValue
308- SILGenFunction::emitLoadOfFunctionIsolation (SILLocation loc,
309- FunctionTypeIsolation isolation,
310- ManagedValue fn) {
371+ SILGenFunction::emitFunctionTypeIsolation (SILLocation loc,
372+ FunctionTypeIsolation isolation,
373+ ManagedValue fn) {
311374 switch (isolation.getKind ()) {
312375
313376 // Parameter-isolated functions don't have a specific actor they're isolated
@@ -318,50 +381,96 @@ SILGenFunction::emitLoadOfFunctionIsolation(SILLocation loc,
318381
319382 // Emit nonisolated by simply emitting Optional.none in the result type.
320383 case FunctionTypeIsolation::Kind::NonIsolated:
321- return B.createManagedOptionalNone (loc,
322- SILType::getOpaqueIsolationType (getASTContext ()));
384+ return emitNonIsolatedIsolation (loc);
323385
324386 // Emit global actor isolation by loading .shared from the global actor,
325387 // 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 () );
329391
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+ }
333400
334- auto optionalAnyActorTy = SILType::getOpaqueIsolationType (getASTContext ());
335- auto anyActorTy = optionalAnyActorTy.getOptionalObjectType ();
336- assert (anyActorTy);
401+ llvm_unreachable (" bad kind" );
402+ }
337403
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+ }
338412
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+ }
342440
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+ }
345447
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);
352457
353- // Inject into `Optional`.
354- auto result = B. createOptionalSome (loc, erasedActor );
458+ case ActorIsolation::Erased:
459+ llvm_unreachable ( " closures cannot directly have erased isolation " );
355460
356- return result;
357- }
461+ case ActorIsolation::GlobalActor:
462+ return emitGlobalActorIsolation (loc,
463+ isolation.getGlobalActor ()->getCanonicalType ());
358464
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+ }
363473 }
364-
365474 llvm_unreachable (" bad kind" );
366475}
367476
0 commit comments