Skip to content

Commit 9dfa174

Browse files
Don't add isolation attributes for deinit when they were inferred from overriden declaration.
But if isolation was inferred from class isolation and matches with isolation of the overriden declaration, attributes are added.
1 parent 5437b31 commit 9dfa174

File tree

2 files changed

+77
-61
lines changed

2 files changed

+77
-61
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 69 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5008,6 +5008,13 @@ static std::optional<unsigned> getIsolatedParamIndex(ValueDecl *value) {
50085008
return std::nullopt;
50095009
}
50105010

5011+
static bool belongsToActor(ValueDecl *value) {
5012+
if (auto nominal = value->getDeclContext()->getSelfNominalTypeDecl()) {
5013+
return nominal->isAnyActor();
5014+
}
5015+
return false;
5016+
}
5017+
50115018
/// Verifies rules about `isolated` parameters for the given decl. There is more
50125019
/// checking about these in TypeChecker::checkParameterList.
50135020
///
@@ -5041,75 +5048,53 @@ static void checkDeclWithIsolatedParameter(ValueDecl *value) {
50415048
}
50425049
}
50435050

5044-
ActorIsolation ActorIsolationRequest::evaluate(
5045-
Evaluator &evaluator, ValueDecl *value) const {
5046-
auto &ctx = value->getASTContext();
5047-
5048-
const bool hasIsolatedSelf =
5049-
evaluateOrDefault(evaluator, HasIsolatedSelfRequest{value}, false);
5050-
5051-
auto addAttributesForActorIsolation = [&](ActorIsolation isolation) {
5052-
ASTContext &ctx = value->getASTContext();
5053-
switch (isolation) {
5054-
case ActorIsolation::Nonisolated:
5055-
case ActorIsolation::NonisolatedUnsafe: {
5056-
value->getAttrs().add(new (ctx) NonisolatedAttr(
5057-
isolation == ActorIsolation::NonisolatedUnsafe, /*implicit=*/true));
5058-
break;
5059-
}
5060-
case ActorIsolation::GlobalActor: {
5061-
auto typeExpr = TypeExpr::createImplicit(isolation.getGlobalActor(), ctx);
5062-
auto attr = CustomAttr::create(ctx, SourceLoc(), typeExpr, /*implicit=*/true);
5063-
value->getAttrs().add(attr);
5051+
static void addAttributesForActorIsolation(ValueDecl *value,
5052+
ActorIsolation isolation) {
5053+
ASTContext &ctx = value->getASTContext();
5054+
switch (isolation) {
5055+
case ActorIsolation::Nonisolated:
5056+
case ActorIsolation::NonisolatedUnsafe: {
5057+
value->getAttrs().add(new (ctx) NonisolatedAttr(
5058+
isolation == ActorIsolation::NonisolatedUnsafe, /*implicit=*/true));
5059+
break;
5060+
}
5061+
case ActorIsolation::GlobalActor: {
5062+
auto typeExpr = TypeExpr::createImplicit(isolation.getGlobalActor(), ctx);
5063+
auto attr =
5064+
CustomAttr::create(ctx, SourceLoc(), typeExpr, /*implicit=*/true);
5065+
value->getAttrs().add(attr);
50645066

5065-
if (isolation.preconcurrency() && !value->getAttrs().hasAttribute<PreconcurrencyAttr>()) {
5066-
auto preconcurrency = new (ctx) PreconcurrencyAttr(/*isImplicit*/true);
5067-
value->getAttrs().add(preconcurrency);
5068-
}
5069-
break;
5067+
if (isolation.preconcurrency() &&
5068+
!value->getAttrs().hasAttribute<PreconcurrencyAttr>()) {
5069+
auto preconcurrency = new (ctx) PreconcurrencyAttr(/*isImplicit*/ true);
5070+
value->getAttrs().add(preconcurrency);
50705071
}
5072+
break;
5073+
}
50715074
case ActorIsolation::Erased:
50725075
llvm_unreachable("cannot add attributes for erased isolation");
50735076
case ActorIsolation::ActorInstance: {
50745077
// Nothing to do. Default value for actors.
5075-
assert(hasIsolatedSelf);
5078+
assert(belongsToActor(value));
50765079
break;
50775080
}
50785081
case ActorIsolation::Unspecified: {
50795082
// Nothing to do. Default value for non-actors.
5080-
assert(!hasIsolatedSelf);
5083+
assert(!belongsToActor(value));
50815084
break;
50825085
}
50835086
}
5084-
};
5085-
5086-
auto isolationFromAttr = getIsolationFromAttributes(value);
5087-
5088-
// No need to isolate implicit deinit, unless there is already an isolated one
5089-
// in the superclass
5090-
if (isa<DestructorDecl>(value)) {
5091-
if (value->isImplicit() && !isolationFromAttr) {
5092-
ValueDecl *overriddenValue = value->getOverriddenDeclOrSuperDeinit();
5093-
ActorIsolation isolation = ActorIsolation::forUnspecified();
5094-
if (overriddenValue) {
5095-
isolation = getOverriddenIsolationFor(value);
5096-
}
5097-
5098-
if (hasIsolatedSelf && isolation.isUnspecified()) {
5099-
// Don't use 'unspecified' for actors, use 'nonisolated' instead.
5100-
// To force generation of the 'nonisolated' attribute in SIL and
5101-
// .swiftmodule
5102-
isolation = ActorIsolation::forNonisolated(false);
5103-
}
5087+
}
51045088

5105-
addAttributesForActorIsolation(isolation);
5106-
return isolation;
5107-
}
5108-
}
5089+
static bool isImplicitDeinit(ValueDecl *value) {
5090+
return isa<DestructorDecl>(value) && value->isImplicit();
5091+
}
51095092

5093+
ActorIsolation ActorIsolationRequest::evaluate(Evaluator &evaluator,
5094+
ValueDecl *value) const {
51105095
// If this declaration has actor-isolated "self", it's isolated to that
51115096
// actor.
5112-
if (hasIsolatedSelf) {
5097+
if (evaluateOrDefault(evaluator, HasIsolatedSelfRequest{value}, false)) {
51135098
auto actor = value->getDeclContext()->getSelfNominalTypeDecl();
51145099
assert(actor && "could not find the actor that 'self' is isolated to");
51155100

@@ -5120,7 +5105,7 @@ ActorIsolation ActorIsolationRequest::evaluate(
51205105
actor->getDeclContext()->isModuleScopeContext() &&
51215106
actor->getDeclContext()->getParentModule()->getABIName().is("Swift")) {
51225107
auto isolation = ActorIsolation::forNonisolated(false);
5123-
addAttributesForActorIsolation(isolation);
5108+
addAttributesForActorIsolation(value, isolation);
51245109
return isolation;
51255110
}
51265111
return ActorIsolation::forActorInstanceSelf(value);
@@ -5144,6 +5129,8 @@ ActorIsolation ActorIsolationRequest::evaluate(
51445129
return ActorIsolation::forActorInstanceParameter(param, *paramIdx);
51455130
}
51465131

5132+
auto isolationFromAttr = getIsolationFromAttributes(value);
5133+
51475134
// Diagnose global state that is not either immutable plus Sendable or
51485135
// isolated to a global actor.
51495136
auto checkGlobalIsolation = [var = dyn_cast<VarDecl>(value)](
@@ -5200,6 +5187,7 @@ ActorIsolation ActorIsolationRequest::evaluate(
52005187
return isolation;
52015188
};
52025189

5190+
ASTContext &ctx = value->getASTContext();
52035191
if (isolationFromAttr && isolationFromAttr->preconcurrency() &&
52045192
!value->getAttrs().hasAttribute<PreconcurrencyAttr>()) {
52055193
auto preconcurrency =
@@ -5303,14 +5291,14 @@ ActorIsolation ActorIsolationRequest::evaluate(
53035291
}
53045292

53055293
// Add nonisolated attribute
5306-
addAttributesForActorIsolation(inferred);
5294+
addAttributesForActorIsolation(value, inferred);
53075295
break;
53085296

53095297
case ActorIsolation::Erased:
53105298
llvm_unreachable("cannot infer erased isolation");
53115299
case ActorIsolation::GlobalActor: {
53125300
// Add global actor attribute
5313-
addAttributesForActorIsolation(inferred);
5301+
addAttributesForActorIsolation(value, inferred);
53145302
break;
53155303
}
53165304

@@ -5455,8 +5443,14 @@ ActorIsolation ActorIsolationRequest::evaluate(
54555443
// If the declaration is in a nominal type (or extension thereof) that
54565444
// has isolation, use that.
54575445
if (auto selfTypeDecl = value->getDeclContext()->getSelfNominalTypeDecl()) {
5458-
if (auto selfTypeIsolation = getActorIsolation(selfTypeDecl))
5459-
return inferredIsolation(selfTypeIsolation, onlyGlobal);
5446+
if (auto selfTypeIsolation = getActorIsolation(selfTypeDecl)) {
5447+
if (isImplicitDeinit(value)) {
5448+
return inferredIsolation(ActorIsolation::forUnspecified(),
5449+
onlyGlobal);
5450+
} else {
5451+
return inferredIsolation(selfTypeIsolation, onlyGlobal);
5452+
}
5453+
}
54605454
}
54615455
}
54625456

@@ -5552,6 +5546,24 @@ bool HasIsolatedSelfRequest::evaluate(
55525546
return false;
55535547
}
55545548

5549+
if (isImplicitDeinit(value)) {
5550+
// Actors don't have inheritance (except inheriting from NSObject),
5551+
// but check for it anyway, just in case it will be re-introduced later.
5552+
ValueDecl *overriddenValue = value->getOverriddenDeclOrSuperDeinit();
5553+
if (overriddenValue) {
5554+
ActorIsolation isolation = getOverriddenIsolationFor(value);
5555+
if (isolation.isActorIsolated()) {
5556+
return isolation.getKind() == ActorIsolation::ActorInstance;
5557+
}
5558+
}
5559+
5560+
// No need to isolate implicit deinit, unless there is already an isolated
5561+
// one in the superclass
5562+
addAttributesForActorIsolation(value,
5563+
ActorIsolation::forNonisolated(false));
5564+
return false;
5565+
}
5566+
55555567
return true;
55565568
}
55575569

test/Concurrency/deinit_isolation_import/test.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ class ProbeExplicit_RoundtripNonisolated: RoundtripNonisolated {
5454
}
5555

5656
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class ProbeImplicit_RoundtripIsolated : RoundtripIsolated {
57-
// CHECK: @objc @MainActor deinit
57+
// Note: Type-checked as isolated, but no @MainActor attribute, because attributes are not added for overriding members
58+
// CHECK: @objc deinit
5859
// CHECK: }
5960
// CHECK-SYMB: ProbeImplicit_RoundtripIsolated.__isolated_deallocating_deinit
6061
// CHECK-SYMB-NEXT: // Isolation: global_actor. type: MainActor
@@ -65,7 +66,7 @@ class ProbeExplicit_RoundtripNonisolated: RoundtripNonisolated {
6566
class ProbeImplicit_RoundtripIsolated: RoundtripIsolated {}
6667

6768
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class ProbeExplicit_RoundtripIsolated : RoundtripIsolated {
68-
// Note: Not @MainActor attribute, because attributes are not added for overriding members
69+
// Note: Type-checked as isolated, but no @MainActor attribute, because attributes are not added for overriding members
6970
// CHECK: @objc deinit
7071
// CHECK: }
7172
// CHECK-SYMB: ProbeExplicit_RoundtripIsolated.__isolated_deallocating_deinit
@@ -183,7 +184,8 @@ class ProbeExplicit_DerivedIsolatedClass: DerivedIsolatedClass {
183184
}
184185

185186
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class ProbeImplicit_BaseIsolatedDealloc : BaseIsolatedDealloc {
186-
// CHECK: @objc @MainActor @preconcurrency deinit
187+
// Note: Type-checked as isolated, but no @MainActor attribute, because attributes are not added for overriding members
188+
// CHECK: @objc deinit
187189
// CHECK: }
188190
// CHECK-SYMB-NOT: ProbeImplicit_BaseIsolatedDealloc.__isolated_deallocating_deinit
189191
// CHECK-SYMB-NOT: @$s4test33ProbeImplicit_BaseIsolatedDeallocCfZ
@@ -193,6 +195,7 @@ class ProbeExplicit_DerivedIsolatedClass: DerivedIsolatedClass {
193195
class ProbeImplicit_BaseIsolatedDealloc: BaseIsolatedDealloc {}
194196

195197
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class ProbeExplicit_BaseIsolatedDealloc : BaseIsolatedDealloc {
198+
// Note: Type-checked as isolated, but no @MainActor attribute, because attributes are not added for overriding members
196199
// CHECK: @objc deinit
197200
// CHECK: }
198201
// CHECK-SYMB-NOT: ProbeExplicit_BaseIsolatedDealloc.__isolated_deallocating_deinit
@@ -213,7 +216,8 @@ class ProbeAnother_BaseIsolatedDealloc: BaseIsolatedDealloc{
213216
#endif
214217

215218
// CHECK-LABEL: @objc @_inheritsConvenienceInitializers class ProbeImplicit_DerivedIsolatedDealloc : DerivedIsolatedDealloc {
216-
// CHECK: @objc @MainActor @preconcurrency deinit
219+
// Note: Type-checked as isolated, but no @MainActor attribute, because attributes are not added for overriding members
220+
// CHECK: @objc deinit
217221
// CHECK: }
218222
// CHECK-SYMB-NOT: ProbeImplicit_DerivedIsolatedDealloc.__isolated_deallocating_deinit
219223
// CHECK-SYMB-NOT: @$s4test36ProbeImplicit_DerivedIsolatedDeallocCfZ

0 commit comments

Comments
 (0)