Skip to content

Commit 5e5af90

Browse files
committed
make synchronous inits have a nonisolated self
1 parent 49b0e25 commit 5e5af90

File tree

6 files changed

+65
-48
lines changed

6 files changed

+65
-48
lines changed

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2043,25 +2043,27 @@ bool LifetimeChecker::isRestrictedActorInitSelf(ActorInitKind *kind) const {
20432043
auto isolation = getActorIsolation(ctor);
20442044
switch (isolation.getKind()) {
20452045
case ActorIsolation::Unspecified:
2046-
llvm_unreachable("actor decl with unspecified isolation?");
2046+
assert(ctor->isObjC() && "unexpected kind of actor ctor isolation");
2047+
break;
20472048

20482049
case ActorIsolation::Independent:
20492050
if (isExplicitlyNonIsolated(ctor))
20502051
return result(ActorInitKind::NonIsolated, true);
2051-
2052-
llvm_unreachable("implicitly nonisolated actor init?");
2052+
break;
20532053

20542054
case ActorIsolation::ActorInstance:
20552055
case ActorIsolation::DistributedActorInstance:
2056-
if (ctor->hasAsync())
2057-
return result(ActorInitKind::PlainAsync, false);
2058-
else
2059-
return result(ActorInitKind::Plain, true);
2056+
break; // handle these below.
20602057

20612058
case ActorIsolation::GlobalActor:
20622059
case ActorIsolation::GlobalActorUnsafe:
20632060
return result(ActorInitKind::GlobalActorIsolated, true);
20642061
};
2062+
2063+
if (ctor->hasAsync())
2064+
return result(ActorInitKind::PlainAsync, false);
2065+
else
2066+
return result(ActorInitKind::Plain, true);
20652067
}
20662068

20672069
return result(ActorInitKind::None, false);

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3230,11 +3230,12 @@ ActorIsolation ActorIsolationRequest::evaluate(
32303230
}
32313231
}
32323232

3233-
// Every actor's convenience init is assumed to be actor-independent.
3233+
// Every actor's convenience or synchronous init is
3234+
// assumed to be actor-independent.
32343235
if (auto nominal = value->getDeclContext()->getSelfNominalTypeDecl())
32353236
if (nominal->isAnyActor())
32363237
if (auto ctor = dyn_cast<ConstructorDecl>(value))
3237-
if (ctor->isConvenienceInit())
3238+
if (ctor->isConvenienceInit() || !ctor->hasAsync())
32383239
defaultIsolation = ActorIsolation::forIndependent();
32393240

32403241
// Function used when returning an inferred isolation.
@@ -3448,11 +3449,10 @@ bool HasIsolatedSelfRequest::evaluate(
34483449
}
34493450
}
34503451

3451-
// In an actor's convenience init, self is not isolated.
34523452
if (auto ctor = dyn_cast<ConstructorDecl>(value)) {
3453-
if (ctor->isConvenienceInit()) {
3453+
// In an actor's convenience or synchronous init, self is not isolated.
3454+
if (ctor->isConvenienceInit() || !ctor->hasAsync())
34543455
return false;
3455-
}
34563456
}
34573457

34583458
return true;

test/Concurrency/actor_definite_init.swift

Lines changed: 7 additions & 7 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-
_ = self.hax
145-
self.helloWorld()
144+
_ = await self.hax
145+
await 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-
_ = self.hax
179-
self.helloWorld()
178+
_ = await self.hax
179+
await 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-
_ = self.hax
213-
self.helloWorld()
212+
_ = await self.hax
213+
await self.helloWorld()
214214
}
215215
}
216216

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

316316
init(v1 start: Int) {
317317
self.counter = start
318-
Task { self.setCounter(start + 1) } // expected-warning {{actor 'self' can only be captured by a closure from an async initializer}}
318+
Task { await 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: 7 additions & 7 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-
_ = self.hax
141-
self.helloWorld()
140+
_ = await self.hax
141+
await 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-
_ = self.hax
175-
self.helloWorld()
174+
_ = await self.hax
175+
await 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-
_ = self.hax
209-
self.helloWorld()
208+
_ = await self.hax
209+
await self.helloWorld()
210210
}
211211
}
212212

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

312312
init(v1 start: Int) {
313313
self.counter = start
314-
Task { self.setCounter(start + 1) } // expected-error {{actor 'self' can only be captured by a closure from an async initializer}}
314+
Task { await 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: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,65 +1007,81 @@ actor Butterfly {
10071007
}
10081008
}
10091009

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`.
1010+
// expected-note@+1 2 {{calls to global function 'takeIsolated' from outside of its actor context are implicitly asynchronous}}
1011+
func takeIsolated(_ val: isolated SelfParamIsolationNonMethod) {}
1012+
func take(_ val: SelfParamIsolationNonMethod) {}
1013+
10141014
actor SelfParamIsolationNonMethod {
10151015
init(s0: Void) {
1016-
Task { self.f() }
1016+
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
1017+
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1018+
acceptAsyncSendableClosureInheriting { self.f() }
10171019

10181020
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10191021
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1020-
Task.detached { self.f() }
1022+
acceptAsyncSendableClosure { self.f() }
1023+
1024+
// expected-error@+1 {{call to actor-isolated global function 'takeIsolated' in a synchronous nonisolated context}}
1025+
takeIsolated(self)
1026+
1027+
take(self)
10211028
}
10221029

10231030
@MainActor init(s1: Void) {
10241031
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10251032
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1026-
Task { self.f() }
1033+
acceptAsyncSendableClosureInheriting { self.f() }
10271034

10281035
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10291036
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1030-
Task.detached { self.f() }
1037+
acceptAsyncSendableClosure { self.f() }
10311038
}
10321039

10331040
init(a1: Void) async {
1034-
Task { self.f() }
1041+
acceptAsyncSendableClosureInheriting { self.f() }
10351042

10361043
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10371044
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1038-
Task.detached { self.f() }
1045+
acceptAsyncSendableClosure { self.f() }
1046+
1047+
takeIsolated(self)
1048+
1049+
take(self)
10391050
}
10401051

10411052
@MainActor init(a2: Void) async {
10421053
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10431054
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1044-
Task { self.f() }
1055+
acceptAsyncSendableClosureInheriting { self.f() }
10451056

10461057
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10471058
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1048-
Task.detached { self.f() }
1059+
acceptAsyncSendableClosure { self.f() }
10491060
}
10501061

10511062
nonisolated init(a3: Void) async {
10521063
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10531064
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1054-
Task { self.f() }
1065+
acceptAsyncSendableClosureInheriting { self.f() }
10551066

10561067
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10571068
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1058-
Task.detached { self.f() }
1069+
acceptAsyncSendableClosure { self.f() }
10591070
}
10601071

10611072
deinit {
10621073
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10631074
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1064-
Task { self.f() }
1075+
acceptAsyncSendableClosureInheriting { self.f() }
10651076

10661077
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10671078
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1068-
Task.detached { self.f() }
1079+
acceptAsyncSendableClosure { self.f() }
1080+
1081+
// expected-error@+1 {{call to actor-isolated global function 'takeIsolated' in a synchronous nonisolated context}}
1082+
takeIsolated(self)
1083+
1084+
take(self)
10691085
}
10701086

10711087
func f() {}
@@ -1074,21 +1090,21 @@ actor SelfParamIsolationNonMethod {
10741090
@MainActor
10751091
final class MainActorInit: Sendable {
10761092
init() {
1077-
Task { self.f() }
1093+
acceptAsyncSendableClosureInheriting { self.f() }
10781094

10791095
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10801096
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1081-
Task.detached { self.f() }
1097+
acceptAsyncSendableClosure { self.f() }
10821098
}
10831099

10841100
deinit {
10851101
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10861102
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1087-
Task { self.f() }
1103+
acceptAsyncSendableClosureInheriting { self.f() }
10881104

10891105
// expected-note@+2 {{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
10901106
// expected-error@+1 {{expression is 'async' but is not marked with 'await'}}
1091-
Task.detached { self.f() }
1107+
acceptAsyncSendableClosure { self.f() }
10921108
}
10931109

10941110
func f() {}

test/decl/class/actor/basic.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@ actor MyActorSubclass2: MyActor { } // expected-error{{actor types do not suppor
1414
// expected-error@+1{{keyword 'class' cannot be used as an identifier here}}
1515
actor class MyActorClass { }
1616

17-
class NonActor { } // expected-note{{overridden declaration is here}}
17+
class NonActor { }
1818

1919
actor NonActorSubclass : NonActor { } // expected-error{{actor types do not support inheritance}}
20-
// expected-error@-1{{actor-isolated initializer 'init()' has different actor isolation from nonisolated overridden declaration}}
2120

2221
// expected-error@+1{{keyword 'class' cannot be used as an identifier here}}
2322
public actor class BobHope {}

0 commit comments

Comments
 (0)