Skip to content

Commit b203f5b

Browse files
committed
remove instances of redundant nonisolated on actor initializers
these appearances are considered errors, because it's already implied by a convenience init. For a synchronous initializer, we can't really describe _what_ it's isolation is right now, but it is not just "nonisolated". So, we leave it ambiguous and say that "nonisolated" is invalid.
1 parent 2d69bc8 commit b203f5b

File tree

6 files changed

+59
-12
lines changed

6 files changed

+59
-12
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4607,6 +4607,12 @@ ERROR(nonisolated_mutable_storage,none,
46074607
ERROR(nonisolated_local_var,none,
46084608
"'nonisolated' can not be applied to local variables",
46094609
())
4610+
ERROR(nonisolated_actor_sync_init,none,
4611+
"'nonisolated' on an actor's synchronous initializer is invalid",
4612+
())
4613+
ERROR(nonisolated_actor_convenience_init,none,
4614+
"'nonisolated' on an actor's convenience initializer is redundant",
4615+
())
46104616

46114617
ERROR(actor_instance_property_wrapper,none,
46124618
"%0 property in property wrapper type %1 cannot be isolated to "

lib/Sema/TypeCheckAttr.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5535,6 +5535,26 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
55355535
return;
55365536
}
55375537
}
5538+
5539+
// `nonisolated` on most actor initializers is invalid or redundant.
5540+
if (auto ctor = dyn_cast<ConstructorDecl>(D)) {
5541+
if (auto nominal = dyn_cast<NominalTypeDecl>(dc)) {
5542+
if (nominal->isAnyActor()) {
5543+
if (ctor->isConvenienceInit()) {
5544+
// all convenience inits are `nonisolated` by default
5545+
diagnoseAndRemoveAttr(attr, diag::nonisolated_actor_convenience_init)
5546+
.warnUntilSwiftVersion(6);
5547+
return;
5548+
5549+
} else if (!ctor->hasAsync()) {
5550+
// the isolation for a synchronous init cannot be `nonisolated`.
5551+
diagnoseAndRemoveAttr(attr, diag::nonisolated_actor_sync_init)
5552+
.warnUntilSwiftVersion(6);
5553+
return;
5554+
}
5555+
}
5556+
}
5557+
}
55385558

55395559
if (auto VD = dyn_cast<ValueDecl>(D)) {
55405560
(void)getActorIsolation(VD);

test/Concurrency/actor_definite_init.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -409,11 +409,11 @@ actor EscapeArtist {
409409
actor Ahmad {
410410
func f() {}
411411

412-
nonisolated init(v1: Void) {
413-
Task.detached { await self.f() } // expected-warning {{actor 'self' cannot be captured by a closure from a non-isolated, designated initializer}}
412+
init(v1: Void) {
413+
Task.detached { await self.f() } // expected-warning {{actor 'self' can only be captured by a closure from an async initializer}}
414414
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
415415

416-
f() // expected-warning {{this use of actor 'self' cannot appear in a non-isolated, designated initializer}}
416+
f() // expected-warning {{this use of actor 'self' can only appear in an async initializer}}
417417
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
418418
}
419419

test/Concurrency/actor_definite_init_swift6.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -406,19 +406,19 @@ actor EscapeArtist {
406406
@available(SwiftStdlib 5.5, *)
407407
actor Ahmad {
408408
func f() {}
409-
410-
nonisolated init(v1: Void) {
411-
Task.detached { await self.f() } // expected-error {{actor 'self' cannot be captured by a closure from a non-isolated, designated initializer}}
412-
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
413-
414-
f() // expected-error {{this use of actor 'self' cannot appear in a non-isolated, designated initializer}}
415-
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
409+
410+
init(v1: Void) {
411+
Task.detached { await self.f() } // expected-error {{actor 'self' can only be captured by a closure from an async initializer}}
412+
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
413+
414+
f() // expected-error {{this use of actor 'self' can only appear in an async initializer}}
415+
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
416416
}
417-
417+
418418
nonisolated init(v2: Void) async {
419419
Task.detached { await self.f() } // expected-error {{actor 'self' cannot be captured by a closure from a non-isolated, designated initializer}} {{3-15=}}
420420
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
421-
421+
422422
f() // expected-error {{this use of actor 'self' cannot appear in a non-isolated, designated initializer}}
423423
// expected-note@-1 {{convenience initializers allow non-isolated use of 'self' once initialized}}
424424
}

test/Concurrency/actor_isolation.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,3 +991,18 @@ class GenericSub1<T>: GenericSuper<[T]> { }
991991

992992
@GenericGlobalActor<T>
993993
class GenericSub2<T>: GenericSuper<[T]> { } // expected-error{{global actor 'GenericGlobalActor<T>'-isolated class 'GenericSub2' has different actor isolation from global actor 'GenericGlobalActor<U>'-isolated superclass 'GenericSuper'}}
994+
995+
/// Diagnostics for `nonisolated` on an actor initializer.
996+
actor Butterfly {
997+
nonisolated init() {} // expected-warning {{'nonisolated' on an actor's synchronous initializer is invalid; this is an error in Swift 6}} {{3-15=}}
998+
999+
nonisolated init(async: Void) async {}
1000+
1001+
nonisolated convenience init(icecream: Void) { // expected-warning {{'nonisolated' on an actor's convenience initializer is redundant; this is an error in Swift 6}} {{3-15=}}
1002+
self.init()
1003+
}
1004+
1005+
nonisolated convenience init(cookies: Void) async { // expected-warning {{'nonisolated' on an actor's convenience initializer is redundant; this is an error in Swift 6}} {{3-15=}}
1006+
self.init()
1007+
}
1008+
}

test/Distributed/distributed_actor_isolation.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,16 @@ func test_params(
175175

176176
// Actor initializer isolation (through typechecking only!)
177177
distributed actor DijonMustard {
178+
nonisolated init(transport: ActorTransport) {} // expected-warning {{'nonisolated' on an actor's synchronous initializer is invalid; this is an error in Swift 6}} {{3-15=}}
179+
178180
convenience init(conv: ActorTransport) {
179181
self.init(transport: conv)
180182
self.f() // expected-error {{actor-isolated instance method 'f()' can not be referenced from a non-isolated context}}
181183
}
182184

183185
func f() {} // expected-note {{distributed actor-isolated instance method 'f()' declared here}}
186+
187+
nonisolated convenience init(conv2: ActorTransport) { // expected-warning {{'nonisolated' on an actor's convenience initializer is redundant; this is an error in Swift 6}} {{3-15=}}
188+
self.init(transport: conv2)
189+
}
184190
}

0 commit comments

Comments
 (0)