@@ -315,6 +315,45 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
315315 return ;
316316}
317317
318+ // FIXME: the callers of ctorHopsInjectedByDefiniteInit is not correct (rdar://87485045)
319+ // we must still set the SGF.ExpectedExecutor field to say that we must
320+ // hop to the executor after every apply in the constructor. This seems to
321+ // happen for the main actor isolated async inits, but not for the plain ones,
322+ // where 'self' is not going to directly be the instance. We have to extend the
323+ // ExecutorBreadcrumb class to detect whether it needs to do a load or not
324+ // in it's emit method.
325+ //
326+ // So, the big problem right now is that for a delegating async actor init,
327+ // after calling an async function, no hop-back is being emitted.
328+
329+ // / Returns true if the given async constructor will have its
330+ // / required actor hops injected later by definite initialization.
331+ static bool ctorHopsInjectedByDefiniteInit (ConstructorDecl *ctor,
332+ ActorIsolation const & isolation) {
333+ // must be async, but we can assume that.
334+ assert (ctor->hasAsync ());
335+
336+ auto *dc = ctor->getDeclContext ();
337+ auto selfClassDecl = dc->getSelfClassDecl ();
338+
339+ // must be an actor
340+ if (!selfClassDecl || !selfClassDecl->isAnyActor ())
341+ return false ;
342+
343+ // must be instance isolated
344+ switch (isolation) {
345+ case ActorIsolation::ActorInstance:
346+ case ActorIsolation::DistributedActorInstance:
347+ return true ;
348+
349+ case ActorIsolation::Unspecified:
350+ case ActorIsolation::Independent:
351+ case ActorIsolation::GlobalActor:
352+ case ActorIsolation::GlobalActorUnsafe:
353+ return false ;
354+ }
355+ }
356+
318357void SILGenFunction::emitValueConstructor (ConstructorDecl *ctor) {
319358 MagicFunctionName = SILGenModule::getMagicFunctionName (ctor);
320359
@@ -360,9 +399,13 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
360399
361400 // Make sure we've hopped to the right global actor, if any.
362401 if (ctor->hasAsync ()) {
363- SILLocation prologueLoc (selfDecl);
364- prologueLoc.markAsPrologue ();
365- emitConstructorPrologActorHop (prologueLoc, getActorIsolation (ctor));
402+ auto isolation = getActorIsolation (ctor);
403+ // if it's not injected by definite init, we do it in the prologue now.
404+ if (!ctorHopsInjectedByDefiniteInit (ctor, isolation)) {
405+ SILLocation prologueLoc (selfDecl);
406+ prologueLoc.markAsPrologue ();
407+ emitConstructorPrologActorHop (prologueLoc, isolation);
408+ }
366409 }
367410
368411 // Create a basic block to jump to for the implicit 'self' return.
@@ -754,10 +797,14 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
754797 selfClassDecl->isDistributedActor () && !isDelegating;
755798
756799 // Make sure we've hopped to the right global actor, if any.
757- if (ctor->hasAsync () && !selfClassDecl->isActor ()) {
758- SILLocation prologueLoc (selfDecl);
759- prologueLoc.markAsPrologue ();
760- emitConstructorPrologActorHop (prologueLoc, getActorIsolation (ctor));
800+ if (ctor->hasAsync ()) {
801+ auto isolation = getActorIsolation (ctor);
802+ // if it's not injected by definite init, we do it in the prologue now.
803+ if (!ctorHopsInjectedByDefiniteInit (ctor, isolation)) {
804+ SILLocation prologueLoc (selfDecl);
805+ prologueLoc.markAsPrologue ();
806+ emitConstructorPrologActorHop (prologueLoc, isolation);
807+ }
761808 }
762809
763810 if (!NeedsBoxForSelf) {
0 commit comments