Skip to content

Commit 95079af

Browse files
Don't generate isolating destructor if dealloc was explicitly isolated in ObjC
1 parent 10b43d7 commit 95079af

File tree

6 files changed

+81
-21
lines changed

6 files changed

+81
-21
lines changed

include/swift/AST/Decl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8762,6 +8762,10 @@ class DestructorDecl : public AbstractFunctionDecl {
87628762
/// Retrieve the Objective-C selector for destructors.
87638763
ObjCSelector getObjCSelector() const;
87648764

8765+
/// Retrives destructor decl from the superclass, or nil if there is no
8766+
/// superclass
8767+
DestructorDecl *getSuperDeinit() const;
8768+
87658769
static bool classof(const Decl *D) {
87668770
return D->getKind() == DeclKind::Destructor;
87678771
}

lib/AST/Decl.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3273,12 +3273,8 @@ ValueDecl *ValueDecl::getOverriddenDeclOrSuperDeinit() const {
32733273
if (auto overridden = getOverriddenDecl()) {
32743274
return overridden;
32753275
}
3276-
if (isa<DestructorDecl>(this)) {
3277-
if (auto classDecl = dyn_cast<ClassDecl>(getDeclContext())) {
3278-
if (auto superclass = classDecl->getSuperclassDecl()) {
3279-
return superclass->getDestructor();
3280-
}
3281-
}
3276+
if (auto dtor = dyn_cast<DestructorDecl>(this)) {
3277+
return dtor->getSuperDeinit();
32823278
}
32833279
return nullptr;
32843280
}
@@ -10794,6 +10790,16 @@ ObjCSelector DestructorDecl::getObjCSelector() const {
1079410790
return ObjCSelector(ctx, 0, ctx.Id_dealloc);
1079510791
}
1079610792

10793+
DestructorDecl *DestructorDecl::getSuperDeinit() const {
10794+
auto declContext = getDeclContext()->getImplementedObjCContext();
10795+
if (auto classDecl = dyn_cast<ClassDecl>(declContext)) {
10796+
if (auto superclass = classDecl->getSuperclassDecl()) {
10797+
return superclass->getDestructor();
10798+
}
10799+
}
10800+
return nullptr;
10801+
}
10802+
1079710803
SourceRange FuncDecl::getSourceRange() const {
1079810804
SourceLoc StartLoc = getStartLoc();
1079910805

lib/SILGen/SILGen.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,8 +1114,7 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
11141114
}
11151115
case SILDeclRef::Kind::Deallocator: {
11161116
auto *dd = cast<DestructorDecl>(constant.getDecl());
1117-
auto ai = swift::getActorIsolation(dd);
1118-
if (ai.isActorIsolated()) {
1117+
if (SILGenFunction::shouldEmitIsolatingDestructor(dd)) {
11191118
auto loc = RegularLocation::getAutoGeneratedLocation(dd);
11201119
preEmitFunction(constant, f, loc);
11211120
PrettyStackTraceSILFunction X("silgen emitIsolatingDestructor", f);
@@ -1574,7 +1573,8 @@ bool SILGenModule::requiresIVarDestroyer(ClassDecl *cd) {
15741573
void SILGenModule::emitObjCAllocatorDestructor(ClassDecl *cd,
15751574
DestructorDecl *dd) {
15761575

1577-
const bool isActorIsolated = getActorIsolation(dd).isActorIsolated();
1576+
const bool isActorIsolated =
1577+
SILGenFunction::shouldEmitIsolatingDestructor(dd);
15781578

15791579
// Emit the isolated deallocating destructor.
15801580
// If emitted, it implements actual deallocating and deallocating destructor
@@ -1663,7 +1663,7 @@ void SILGenModule::emitDestructor(ClassDecl *cd, DestructorDecl *dd) {
16631663
// Emit the isolated deallocating destructor.
16641664
// If emitted, it implements actual deallocating and deallocating destructor
16651665
// only switches executor
1666-
if (getActorIsolation(dd).isActorIsolated()) {
1666+
if (SILGenFunction::shouldEmitIsolatingDestructor(dd)) {
16671667
SILDeclRef deallocator(dd, SILDeclRef::Kind::IsolatedDeallocator);
16681668
emitFunctionDefinition(deallocator,
16691669
getFunction(deallocator, ForDefinition));

lib/SILGen/SILGenDestructor.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,28 @@ static AccessorDecl *getUnownedExecutorGetter(ASTContext &ctx,
295295
return nullptr;
296296
}
297297

298+
bool SILGenFunction::shouldEmitIsolatingDestructor(DestructorDecl *dd) {
299+
auto ai = swift::getActorIsolation(dd);
300+
if (!ai.isActorIsolated()) {
301+
return false;
302+
}
303+
DestructorDecl *firstIsolated = dd;
304+
while (true) {
305+
DestructorDecl *next = firstIsolated->getSuperDeinit();
306+
if (!next)
307+
break;
308+
auto ai = swift::getActorIsolation(next);
309+
if (!ai.isActorIsolated())
310+
break;
311+
firstIsolated = next;
312+
}
313+
314+
// If isolation was intoduced in ObjC code, then we assume that ObjC code also
315+
// overrides retain/release to make sure that dealloc is called on the correct
316+
// executor in the first place.
317+
return firstIsolated->getClangNode().isNull();
318+
}
319+
298320
void SILGenFunction::emitIsolatingDestructor(DestructorDecl *dd) {
299321
MagicFunctionName = DeclName(SGM.M.getASTContext().getIdentifier("deinit"));
300322

lib/SILGen/SILGenFunction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
828828
/// definite initialization.
829829
bool isCtorWithHopsInjectedByDefiniteInit();
830830

831+
/// Checks if isolating destructor is needed.
832+
static bool shouldEmitIsolatingDestructor(DestructorDecl *dd);
833+
831834
/// Generates code for a struct constructor.
832835
/// This allocates the new 'self' value, emits the
833836
/// body code, then returns the final initialized 'self'.

test/Concurrency/deinit_isolation_import/test.swift

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
// Note: intentionally importing Alpha implicitly
2121
import Beta
2222

23+
@globalActor final actor AnotherActor {
24+
static let shared = AnotherActor()
25+
}
26+
2327
@MainActor
2428
func isolatedFunc() {} // expected-note 3{{calls to global function 'isolatedFunc()' from outside of its actor context are implicitly asynchronous}}
2529

@@ -181,8 +185,8 @@ class ProbeExplicit_DerivedIsolatedClass: DerivedIsolatedClass {
181185
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class ProbeImplicit_BaseIsolatedDealloc : BaseIsolatedDealloc {
182186
// CHECK: @objc @MainActor @preconcurrency deinit
183187
// CHECK: }
184-
// CHECK-SYMB: // ProbeImplicit_BaseIsolatedDealloc.__isolated_deallocating_deinit
185-
// CHECK-SYMB: sil private [ossa] @$s4test33ProbeImplicit_BaseIsolatedDeallocCfZ : $@convention(thin) (@owned ProbeImplicit_BaseIsolatedDealloc) -> () {
188+
// CHECK-SYMB-NOT: ProbeImplicit_BaseIsolatedDealloc.__isolated_deallocating_deinit
189+
// CHECK-SYMB-NOT: @$s4test33ProbeImplicit_BaseIsolatedDeallocCfZ
186190
// CHECK-SYMB: // ProbeImplicit_BaseIsolatedDealloc.__deallocating_deinit
187191
// CHECK-SYMB-NEXT: // Isolation: nonisolated
188192
// CHECK-SYMB-NEXT: sil hidden [ossa] @$s4test33ProbeImplicit_BaseIsolatedDeallocCfD : $@convention(method) (@owned ProbeImplicit_BaseIsolatedDealloc) -> () {
@@ -191,9 +195,8 @@ class ProbeImplicit_BaseIsolatedDealloc: BaseIsolatedDealloc {}
191195
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class ProbeExplicit_BaseIsolatedDealloc : BaseIsolatedDealloc {
192196
// CHECK: @objc deinit
193197
// CHECK: }
194-
// CHECK-SYMB: // ProbeExplicit_BaseIsolatedDealloc.__isolated_deallocating_deinit
195-
// CHECK-SYMB-NEXT: // Isolation: global_actor. type: MainActor
196-
// CHECK-SYMB-NEXT: sil private [ossa] @$s4test33ProbeExplicit_BaseIsolatedDeallocCfZ : $@convention(thin) (@owned ProbeExplicit_BaseIsolatedDealloc) -> () {
198+
// CHECK-SYMB-NOT: ProbeExplicit_BaseIsolatedDealloc.__isolated_deallocating_deinit
199+
// CHECK-SYMB-NOT: @$s4test33ProbeExplicit_BaseIsolatedDeallocCfZ
197200
// CHECK-SYMB: // ProbeExplicit_BaseIsolatedDealloc.__deallocating_deinit
198201
// CHECK-SYMB-NEXT: // Isolation: nonisolated
199202
// CHECK-SYMB-NEXT: sil hidden [ossa] @$s4test33ProbeExplicit_BaseIsolatedDeallocCfD : $@convention(method) (@owned ProbeExplicit_BaseIsolatedDealloc) -> () {
@@ -203,12 +206,17 @@ class ProbeExplicit_BaseIsolatedDealloc: BaseIsolatedDealloc {
203206
}
204207
}
205208

209+
#if !SILGEN
210+
class ProbeAnother_BaseIsolatedDealloc: BaseIsolatedDealloc{
211+
@AnotherActor deinit {} // expected-error {{global actor 'AnotherActor'-isolated deinitializer 'deinit' has different actor isolation from main actor-isolated overridden declaration}}
212+
}
213+
#endif
214+
206215
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class ProbeImplicit_DerivedIsolatedDealloc : DerivedIsolatedDealloc {
207216
// CHECK: @objc @MainActor @preconcurrency deinit
208217
// CHECK: }
209-
// CHECK-SYMB: // ProbeImplicit_DerivedIsolatedDealloc.__isolated_deallocating_deinit
210-
// CHECK-SYMB-NEXT: // Isolation: global_actor. type: MainActor
211-
// CHECK-SYMB: sil private [ossa] @$s4test36ProbeImplicit_DerivedIsolatedDeallocCfZ : $@convention(thin) (@owned ProbeImplicit_DerivedIsolatedDealloc) -> () {
218+
// CHECK-SYMB-NOT: ProbeImplicit_DerivedIsolatedDealloc.__isolated_deallocating_deinit
219+
// CHECK-SYMB-NOT: @$s4test36ProbeImplicit_DerivedIsolatedDeallocCfZ
212220
// CHECK-SYMB: // ProbeImplicit_DerivedIsolatedDealloc.__deallocating_deinit
213221
// CHECK-SYMB-NEXT: // Isolation: nonisolated
214222
// CHECK-SYMB-NEXT: sil hidden [ossa] @$s4test36ProbeImplicit_DerivedIsolatedDeallocCfD : $@convention(method) (@owned ProbeImplicit_DerivedIsolatedDealloc) -> () {
@@ -217,9 +225,8 @@ class ProbeImplicit_DerivedIsolatedDealloc: DerivedIsolatedDealloc {}
217225
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class ProbeExplicit_DerivedIsolatedDealloc : DerivedIsolatedDealloc {
218226
// CHECK: @objc deinit
219227
// CHECK: }
220-
// CHECK-SYMB: // ProbeExplicit_DerivedIsolatedDealloc.__isolated_deallocating_deinit
221-
// CHECK-SYMB-NEXT: // Isolation: global_actor. type: MainActor
222-
// CHECK-SYMB-NEXT: sil private [ossa] @$s4test36ProbeExplicit_DerivedIsolatedDeallocCfZ : $@convention(thin) (@owned ProbeExplicit_DerivedIsolatedDealloc) -> () {
228+
// CHECK-SYMB-NOT: ProbeExplicit_DerivedIsolatedDealloc.__isolated_deallocating_deinit
229+
// CHECK-SYMB-NOT: @$s4test36ProbeExplicit_DerivedIsolatedDeallocCfZ
223230
// CHECK-SYMB: // ProbeExplicit_DerivedIsolatedDealloc.__deallocating_deinit
224231
// CHECK-SYMB-NEXT: // Isolation: nonisolated
225232
// CHECK-SYMB-NEXT: sil hidden [ossa] @$s4test36ProbeExplicit_DerivedIsolatedDeallocCfD : $@convention(method) (@owned ProbeExplicit_DerivedIsolatedDealloc) -> () {
@@ -229,6 +236,12 @@ class ProbeExplicit_DerivedIsolatedDealloc: DerivedIsolatedDealloc {
229236
}
230237
}
231238

239+
#if !SILGEN
240+
class ProbeAnother_DerivedIsolatedDealloc: DerivedIsolatedDealloc{
241+
@AnotherActor deinit {} // expected-error {{global actor 'AnotherActor'-isolated deinitializer 'deinit' has different actor isolation from main actor-isolated overridden declaration}}
242+
}
243+
#endif
244+
232245
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class ProbeImplicit_DeallocIsolatedFromProtocol : DeallocIsolatedFromProtocol {
233246
// CHECK: @objc deinit
234247
// CHECK: }
@@ -239,6 +252,10 @@ class ProbeExplicit_DerivedIsolatedDealloc: DerivedIsolatedDealloc {
239252
// CHECK-SYMB-NEXT: sil hidden [ossa] @$s4test41ProbeImplicit_DeallocIsolatedFromProtocolCfD : $@convention(method) (@owned ProbeImplicit_DeallocIsolatedFromProtocol) -> () {
240253
class ProbeImplicit_DeallocIsolatedFromProtocol: DeallocIsolatedFromProtocol {}
241254

255+
class ProbeAnother_DeallocIsolatedFromProtocol: DeallocIsolatedFromProtocol {
256+
@AnotherActor deinit {} // ok, base is not isolated
257+
}
258+
242259
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class ProbeImplicit_DeallocIsolatedFromCategory : DeallocIsolatedFromCategory {
243260
// CHECK: @objc deinit
244261
// CHECK: }
@@ -249,6 +266,10 @@ class ProbeImplicit_DeallocIsolatedFromProtocol: DeallocIsolatedFromProtocol {}
249266
// CHECK-SYMB-NEXT: sil hidden [ossa] @$s4test41ProbeImplicit_DeallocIsolatedFromCategoryCfD : $@convention(method) (@owned ProbeImplicit_DeallocIsolatedFromCategory) -> () {
250267
class ProbeImplicit_DeallocIsolatedFromCategory: DeallocIsolatedFromCategory {}
251268

269+
class ProbeAnother_DeallocIsolatedFromCategory: DeallocIsolatedFromCategory {
270+
@AnotherActor deinit {} // ok, base is not isolated
271+
}
272+
252273
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class ProbeImplicit_DeallocIsolatedFromExtension : DeallocIsolatedFromExtension {
253274
// CHECK: @objc deinit
254275
// CHECK: }
@@ -258,3 +279,7 @@ class ProbeImplicit_DeallocIsolatedFromCategory: DeallocIsolatedFromCategory {}
258279
// CHECK-SYMB-NEXT: // Isolation: nonisolated
259280
// CHECK-SYMB-NEXT: sil hidden [ossa] @$s4test42ProbeImplicit_DeallocIsolatedFromExtensionCfD : $@convention(method) (@owned ProbeImplicit_DeallocIsolatedFromExtension) -> () {
260281
class ProbeImplicit_DeallocIsolatedFromExtension: DeallocIsolatedFromExtension {}
282+
283+
class ProbeAnother_DeallocIsolatedFromExtension: DeallocIsolatedFromExtension {
284+
@AnotherActor deinit {} // ok, base is not isolated
285+
}

0 commit comments

Comments
 (0)