Skip to content

Commit 1120bee

Browse files
Reject isolation attributes on deinit in value types
1 parent da75f5f commit 1120bee

File tree

3 files changed

+81
-1
lines changed

3 files changed

+81
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5939,6 +5939,9 @@ ERROR(async_unavailable_decl,none,
59395939
ERROR(isolated_deinit_no_isolation,none,
59405940
"deinit is marked isolated, but containing class %0 is not isolated to an actor",
59415941
(DeclName))
5942+
ERROR(isolated_deinit_on_value_type,none,
5943+
"only classes and actors can have isolated deinit",
5944+
())
59425945

59435946
//------------------------------------------------------------------------------
59445947
// MARK: String Processing

lib/Sema/TypeCheckAttr.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,18 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
109109
return true;
110110
}
111111

112+
void diagnoseIsolatedDeinitInValueTypes(DeclAttribute *attr) {
113+
if (isa<DestructorDecl>(D)) {
114+
if (auto nominal = dyn_cast<NominalTypeDecl>(D->getDeclContext())) {
115+
if (!isa<ClassDecl>(nominal)) {
116+
// only classes and actors can have isolated deinit.
117+
diagnoseAndRemoveAttr(attr, diag::isolated_deinit_on_value_type);
118+
return;
119+
}
120+
}
121+
}
122+
}
123+
112124
template <typename... ArgTypes>
113125
InFlightDiagnostic diagnose(ArgTypes &&... Args) const {
114126
return Ctx.Diags.diagnose(std::forward<ArgTypes>(Args)...);
@@ -130,7 +142,6 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
130142
IGNORED_ATTR(HasMissingDesignatedInitializers)
131143
IGNORED_ATTR(InheritsConvenienceInitializers)
132144
IGNORED_ATTR(Inline)
133-
IGNORED_ATTR(Isolated)
134145
IGNORED_ATTR(ObjCBridged)
135146
IGNORED_ATTR(ObjCNonLazyRealization)
136147
IGNORED_ATTR(ObjCRuntimeName)
@@ -330,6 +341,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
330341

331342
void visitReasyncAttr(ReasyncAttr *attr);
332343
void visitNonisolatedAttr(NonisolatedAttr *attr);
344+
void visitIsolatedAttr(IsolatedAttr *attr);
333345

334346
void visitNoImplicitCopyAttr(NoImplicitCopyAttr *attr);
335347

@@ -4211,6 +4223,7 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
42114223
// If the nominal type is a global actor, let the global actor attribute
42124224
// retrieval request perform checking for us.
42134225
if (nominal->isGlobalActor()) {
4226+
diagnoseIsolatedDeinitInValueTypes(attr);
42144227
(void)D->getGlobalActorAttr();
42154228
if (auto value = dyn_cast<ValueDecl>(D)) {
42164229
(void)getActorIsolation(value);
@@ -7127,11 +7140,17 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
71277140
}
71287141
}
71297142

7143+
diagnoseIsolatedDeinitInValueTypes(attr);
7144+
71307145
if (auto VD = dyn_cast<ValueDecl>(D)) {
71317146
(void)getActorIsolation(VD);
71327147
}
71337148
}
71347149

7150+
void AttributeChecker::visitIsolatedAttr(IsolatedAttr *attr) {
7151+
diagnoseIsolatedDeinitInValueTypes(attr);
7152+
}
7153+
71357154
void AttributeChecker::visitGlobalActorAttr(GlobalActorAttr *attr) {
71367155
auto nominal = dyn_cast<NominalTypeDecl>(D);
71377156
if (!nominal)
@@ -7146,6 +7165,8 @@ void AttributeChecker::visitGlobalActorAttr(GlobalActorAttr *attr) {
71467165
return;
71477166
}
71487167

7168+
diagnoseIsolatedDeinitInValueTypes(attr);
7169+
71497170
(void)nominal->isGlobalActor();
71507171
}
71517172

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// RUN: %target-swift-frontend -disable-availability-checking -parse-as-library -emit-silgen -verify %s
2+
3+
@globalActor final actor FirstActor {
4+
static let shared = FirstActor()
5+
}
6+
7+
struct AS: ~Copyable {
8+
@FirstActor deinit {} // expected-error {{only classes and actors can have isolated deinit}}
9+
}
10+
11+
@FirstActor
12+
struct BS: ~Copyable {
13+
isolated deinit {} // expected-error {{only classes and actors can have isolated deinit}}
14+
}
15+
16+
struct CS: ~Copyable {
17+
isolated deinit {} // expected-error {{only classes and actors can have isolated deinit}}
18+
}
19+
20+
struct DS: ~Copyable {
21+
nonisolated deinit {} // expected-error {{only classes and actors can have isolated deinit}}
22+
}
23+
24+
struct ES: ~Copyable {
25+
@FirstActor isolated deinit {} // expected-error 2 {{only classes and actors can have isolated deinit}}
26+
}
27+
28+
enum AE: ~Copyable {
29+
// expected-error@+1 {{deinitializers are not yet supported on noncopyable enums}}
30+
@FirstActor deinit {} // expected-error {{only classes and actors can have isolated deinit}}
31+
}
32+
33+
@FirstActor
34+
enum BE: ~Copyable {
35+
case dummy
36+
// expected-error@+1 {{deinitializers are not yet supported on noncopyable enums}}
37+
isolated deinit {} // expected-error {{only classes and actors can have isolated deinit}}
38+
}
39+
40+
enum CE: ~Copyable {
41+
case dummy
42+
// expected-error@+1 {{deinitializers are not yet supported on noncopyable enums}}
43+
isolated deinit {} // expected-error {{only classes and actors can have isolated deinit}}
44+
}
45+
46+
enum DE: ~Copyable {
47+
case dummy
48+
// expected-error@+1 {{deinitializers are not yet supported on noncopyable enums}}
49+
nonisolated deinit {} // expected-error {{only classes and actors can have isolated deinit}}
50+
}
51+
52+
enum EE: ~Copyable {
53+
case dummy
54+
// expected-error@+1 {{deinitializers are not yet supported on noncopyable enums}}
55+
@FirstActor isolated deinit {} // expected-error 2 {{only classes and actors can have isolated deinit}}
56+
}

0 commit comments

Comments
 (0)