Skip to content

Commit 49b0e25

Browse files
committed
fix the isolation of the self param in ctors and dtors
The isolation of `self` was missing on its ParamDecl of ctors of an actor, leading to situations where closures that should inherit the isolation of the ctor, not actually inheriting it because they only inspect the ParamDecl. This patch makes it so that both inits and deinits also get their `self` isolation by making a query in the type checker. resolves rdar://84682865
1 parent 59fbafa commit 49b0e25

File tree

4 files changed

+109
-23
lines changed

4 files changed

+109
-23
lines changed

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2936,7 +2936,6 @@ AnyFunctionType::Param swift::computeSelfParam(AbstractFunctionDecl *AFD,
29362936
bool isStatic = false;
29372937
SelfAccessKind selfAccess = SelfAccessKind::NonMutating;
29382938
bool isDynamicSelf = false;
2939-
bool isIsolated = false;
29402939

29412940
if (auto *FD = dyn_cast<FuncDecl>(AFD)) {
29422941
isStatic = FD->isStatic();
@@ -2954,10 +2953,6 @@ AnyFunctionType::Param swift::computeSelfParam(AbstractFunctionDecl *AFD,
29542953
else if (wantDynamicSelf && FD->hasDynamicSelfResult())
29552954
isDynamicSelf = true;
29562955

2957-
// If this is a non-static method within an actor, the 'self' parameter
2958-
// is isolated if this declaration is isolated.
2959-
isIsolated = evaluateOrDefault(
2960-
Ctx.evaluator, HasIsolatedSelfRequest{AFD}, false);
29612956
} else if (auto *CD = dyn_cast<ConstructorDecl>(AFD)) {
29622957
if (isInitializingCtor) {
29632958
// initializing constructors of value types always have an implicitly
@@ -3014,6 +3009,10 @@ AnyFunctionType::Param swift::computeSelfParam(AbstractFunctionDecl *AFD,
30143009
if (isStatic)
30153010
return AnyFunctionType::Param(MetatypeType::get(selfTy, Ctx));
30163011

3012+
// `self` is isolated if typechecker says the function is isolated to it.
3013+
bool isIsolated =
3014+
evaluateOrDefault(Ctx.evaluator, HasIsolatedSelfRequest{AFD}, false);
3015+
30173016
auto flags = ParameterTypeFlags().withIsolated(isIsolated);
30183017
switch (selfAccess) {
30193018
case SelfAccessKind::Consuming:

test/Concurrency/actor_definite_init.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ actor MyActor {
141141

142142
Task { // expected-warning {{actor 'self' can only be captured by a closure from an async initializer}}
143143
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
144-
_ = await self.hax
145-
await self.helloWorld()
144+
_ = self.hax
145+
self.helloWorld()
146146
}
147147
}
148148

@@ -175,8 +175,8 @@ actor MyActor {
175175

176176
Task { // expected-warning {{actor 'self' can only be captured by a closure from an async initializer}}
177177
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
178-
_ = await self.hax
179-
await self.helloWorld()
178+
_ = self.hax
179+
self.helloWorld()
180180
}
181181
}
182182

@@ -209,8 +209,8 @@ actor MyActor {
209209

210210
Task { // expected-warning {{actor 'self' can only be captured by a closure from an async initializer}}
211211
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
212-
_ = await self.hax
213-
await self.helloWorld()
212+
_ = self.hax
213+
self.helloWorld()
214214
}
215215
}
216216

@@ -267,8 +267,8 @@ actor MyActor {
267267
computedProp = 1
268268

269269
Task {
270-
_ = await self.hax
271-
await self.helloWorld()
270+
_ = self.hax
271+
self.helloWorld()
272272
}
273273
}
274274

@@ -315,7 +315,7 @@ actor X {
315315

316316
init(v1 start: Int) {
317317
self.counter = start
318-
Task { await self.setCounter(start + 1) } // expected-warning {{actor 'self' can only be captured by a closure from an async initializer}}
318+
Task { self.setCounter(start + 1) } // expected-warning {{actor 'self' can only be captured by a closure from an async initializer}}
319319
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
320320

321321
if self.counter != start {

test/Concurrency/actor_definite_init_swift6.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ actor MyActor {
137137

138138
Task { // expected-error {{actor 'self' can only be captured by a closure from an async initializer}}
139139
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
140-
_ = await self.hax
141-
await self.helloWorld()
140+
_ = self.hax
141+
self.helloWorld()
142142
}
143143
}
144144

@@ -171,8 +171,8 @@ actor MyActor {
171171

172172
Task { // expected-error {{actor 'self' can only be captured by a closure from an async initializer}}
173173
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
174-
_ = await self.hax
175-
await self.helloWorld()
174+
_ = self.hax
175+
self.helloWorld()
176176
}
177177
}
178178

@@ -205,8 +205,8 @@ actor MyActor {
205205

206206
Task { // expected-error {{actor 'self' can only be captured by a closure from an async initializer}}
207207
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
208-
_ = await self.hax
209-
await self.helloWorld()
208+
_ = self.hax
209+
self.helloWorld()
210210
}
211211
}
212212

@@ -263,8 +263,8 @@ actor MyActor {
263263
computedProp = 1
264264

265265
Task {
266-
_ = await self.hax
267-
await self.helloWorld()
266+
_ = self.hax
267+
self.helloWorld()
268268
}
269269
}
270270

@@ -311,7 +311,7 @@ actor X {
311311

312312
init(v1 start: Int) {
313313
self.counter = start
314-
Task { await self.setCounter(start + 1) } // expected-error {{actor 'self' can only be captured by a closure from an async initializer}}
314+
Task { self.setCounter(start + 1) } // expected-error {{actor 'self' can only be captured by a closure from an async initializer}}
315315
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
316316

317317
if self.counter != start {

test/Concurrency/actor_isolation.swift

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,3 +1006,90 @@ actor Butterfly {
10061006
self.init()
10071007
}
10081008
}
1009+
1010+
// Test the isolation of `self` in constructors and deinits of an actor.
1011+
// We know that Task.init accepts a special closure that inherits the isolation
1012+
// of the context based on the isolation of values captured in the closure,
1013+
// like `self`.
1014+
actor SelfParamIsolationNonMethod {
1015+
init(s0: Void) {
1016+
Task { self.f() }
1017+
1018+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1019+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1020+
Task.detached { self.f() }
1021+
}
1022+
1023+
@MainActor init(s1: Void) {
1024+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1025+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1026+
Task { self.f() }
1027+
1028+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1029+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1030+
Task.detached { self.f() }
1031+
}
1032+
1033+
init(a1: Void) async {
1034+
Task { self.f() }
1035+
1036+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1037+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1038+
Task.detached { self.f() }
1039+
}
1040+
1041+
@MainActor init(a2: Void) async {
1042+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1043+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1044+
Task { self.f() }
1045+
1046+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1047+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1048+
Task.detached { self.f() }
1049+
}
1050+
1051+
nonisolated init(a3: Void) async {
1052+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1053+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1054+
Task { self.f() }
1055+
1056+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1057+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1058+
Task.detached { self.f() }
1059+
}
1060+
1061+
deinit {
1062+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1063+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1064+
Task { self.f() }
1065+
1066+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1067+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1068+
Task.detached { self.f() }
1069+
}
1070+
1071+
func f() {}
1072+
}
1073+
1074+
@MainActor
1075+
final class MainActorInit: Sendable {
1076+
init() {
1077+
Task { self.f() }
1078+
1079+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1080+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1081+
Task.detached { self.f() }
1082+
}
1083+
1084+
deinit {
1085+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1086+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1087+
Task { self.f() }
1088+
1089+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1090+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1091+
Task.detached { self.f() }
1092+
}
1093+
1094+
func f() {}
1095+
}

0 commit comments

Comments
 (0)