@@ -76,8 +76,11 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
7676 resultSelfValue = selfValue;
7777 }
7878
79+
7980 if (cd->isDistributedActor ()) {
80- injectDistributedActorDestructorLifecycleCall (dd, selfValue);
81+ SILBasicBlock *continueBB = createBasicBlock ();
82+ injectDistributedActorDestructorLifecycleCall (dd, selfValue, continueBB);
83+ B.emitBlock (continueBB);
8184 }
8285
8386 ArgumentScope S (*this , Loc);
@@ -106,19 +109,8 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
106109 B.createReturn (returnLoc, resultSelfValue);
107110}
108111
109- static AccessorDecl *getActorTransportGetter (ASTContext &ctx,
110- ProtocolDecl *distributedActorProtocol) {
111- for (auto member: distributedActorProtocol->getAllMembers ()) {
112- if (auto var = dyn_cast<VarDecl>(member)) {
113- if (var->getName () == ctx.Id_unownedExecutor )
114- return var->getAccessor (AccessorKind::Get);
115- }
116- }
117- return nullptr ;
118- }
119-
120112void SILGenFunction::injectDistributedActorDestructorLifecycleCall (
121- DestructorDecl *dd, SILValue selfValue) {
113+ DestructorDecl *dd, SILValue selfValue, SILBasicBlock *continueBB ) {
122114 ASTContext &ctx = getASTContext ();
123115
124116 auto cd = cast<ClassDecl>(dd->getDeclContext ());
@@ -129,6 +121,10 @@ void SILGenFunction::injectDistributedActorDestructorLifecycleCall(
129121 if (dd->isImplicit ())
130122 Loc.markAutoGenerated ();
131123
124+ auto selfDecl = dd->getImplicitSelfDecl ();
125+ auto selfManagedValue = ManagedValue::forUnmanaged (selfValue);
126+ auto selfType = selfDecl->getType ();
127+
132128 // ==== locate: self.actorAddress
133129 auto addressVarDeclRefs = cd->lookupDirect (ctx.Id_actorAddress );
134130 assert (addressVarDeclRefs.size () == 1 );
@@ -142,43 +138,82 @@ void SILGenFunction::injectDistributedActorDestructorLifecycleCall(
142138 auto transportVarDeclRefs = cd->lookupDirect (ctx.Id_actorTransport );
143139 assert (transportVarDeclRefs.size () == 1 );
144140 auto *transportVarDeclRef = dyn_cast<VarDecl>(transportVarDeclRefs.front ());
145- assert (transportVarDeclRef);
146141 auto transportRef =
147142 B.createRefElementAddr (Loc, selfValue, transportVarDeclRef,
148143 getLoweredType (transportVarDeclRef->getType ()));
149- assert (transportRef);
150144
151145 // locate: self.transport.resignAddress(...)
152146 auto *transportDecl = ctx.getActorTransportDecl ();
153147 auto resignFnDecls = transportDecl->lookupDirect (ctx.Id_resignAddress );
154148 assert (resignFnDecls.size () == 1 );
155- ValueDecl *resignFnDecl = resignFnDecls.front ();
156- assert (resignFnDecl && " Unable to find 'resignAddress' on ActorTransport" );
149+ auto *resignFnDecl = resignFnDecls.front ();
157150 auto resignFnRef = SILDeclRef (resignFnDecl);
158151
159- auto openedTransport =
160- OpenedArchetypeType::get (transportVarDeclRef->getType ());
152+ // we only transport.resignAddress if we are a local actor,
153+ // and thus the address was created by transport.assignAddress.
154+ auto isRemoteBB = createBasicBlock ();
155+ auto isLocalBB = createBasicBlock ();
161156
162- auto transportAddr = B.createOpenExistentialAddr (
163- Loc, /* operand=*/ transportRef, getLoweredType (openedTransport),
164- OpenedExistentialAccess::Immutable);
157+ // if __isRemoteActor(self) {
158+ // ...
159+ // } else {
160+ // ...
161+ // }
162+ {
163+ FuncDecl *isRemoteFn = ctx.getIsRemoteDistributedActor ();
164+ assert (isRemoteFn && " Could not find 'is remote' function, is the "
165+ " '_Distributed' module available?" );
166+
167+ ManagedValue selfAnyObject =
168+ B.createInitExistentialRef (Loc, getLoweredType (ctx.getAnyObjectType ()),
169+ CanType (selfType), selfManagedValue, {});
170+ auto result = emitApplyOfLibraryIntrinsic (
171+ Loc, isRemoteFn, SubstitutionMap (), {selfAnyObject}, SGFContext ());
172+
173+ SILValue isRemoteResult =
174+ std::move (result).forwardAsSingleValue (*this , Loc);
175+ SILValue isRemoteResultUnwrapped =
176+ emitUnwrapIntegerResult (Loc, isRemoteResult);
177+
178+ B.createCondBranch (Loc, isRemoteResultUnwrapped, isRemoteBB, isLocalBB);
179+ }
165180
166- auto resignFnType = SGM.M .Types .getConstantFunctionType (
167- TypeExpansionContext::minimal (), resignFnRef);
181+ // if remote
182+ // === <noop>
183+ {
184+ B.emitBlock (isRemoteBB);
185+ // noop, remote actors don't do anything in their deinit
186+ B.createBranch (Loc, continueBB);
187+ }
168188
169- auto witness = B.createWitnessMethod (
170- Loc, openedTransport, ProtocolConformanceRef (transportDecl), resignFnRef,
171- SILType::getPrimitiveObjectType (resignFnType));
189+ // if local
190+ // === self.transport.resignAddress(self.address)
191+ {
192+ B.emitBlock (isLocalBB);
172193
173- auto subs = SubstitutionMap::getProtocolSubstitutions (
174- transportDecl, openedTransport, ProtocolConformanceRef (transportDecl));
194+ auto openedTransport =
195+ OpenedArchetypeType::get (transportVarDeclRef->getType ());
196+ auto transportAddr = B.createOpenExistentialAddr (
197+ Loc, /* operand=*/ transportRef, getLoweredType (openedTransport),
198+ OpenedExistentialAccess::Immutable);
175199
176- SmallVector<SILValue, 2 > params;
177- params.push_back (addressRef);
178- params.push_back (transportAddr); // self for the call, as last param
200+ auto resignFnType = SGM.M .Types .getConstantFunctionType (
201+ TypeExpansionContext::minimal (), resignFnRef);
179202
180- // === self.transport.resignAddress(self.address)
181- B.createApply (Loc, witness, subs, params);
203+ auto witness = B.createWitnessMethod (
204+ Loc, openedTransport, ProtocolConformanceRef (transportDecl),
205+ resignFnRef, SILType::getPrimitiveObjectType (resignFnType));
206+
207+ auto subs = SubstitutionMap::getProtocolSubstitutions (
208+ transportDecl, openedTransport, ProtocolConformanceRef (transportDecl));
209+
210+ SmallVector<SILValue, 2 > params;
211+ params.push_back (addressRef);
212+ params.push_back (transportAddr); // self for the call, as last param
213+
214+ B.createApply (Loc, witness, subs, params);
215+ B.createBranch (Loc, continueBB);
216+ }
182217}
183218
184219void SILGenFunction::emitDeallocatingDestructor (DestructorDecl *dd) {
0 commit comments