Skip to content

Commit c9bfe8c

Browse files
committed
[Concurrency] Don't allow subclasses of nonisolated classes to add global
actor isolation. Adding global actor isolation via subclassing admits data races because actor-isolated types are Sendable while nonisolated classes are not (unless otherwise annotated), so this allowed bypassing Sendable checking.
1 parent fad02e3 commit c9bfe8c

File tree

4 files changed

+15
-4
lines changed

4 files changed

+15
-4
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4051,11 +4051,13 @@ static bool checkClassGlobalActorIsolation(
40514051
return false;
40524052

40534053
// Check the superclass's isolation.
4054+
bool downgradeToWarning = false;
40544055
auto superIsolation = getActorIsolation(superclassDecl);
40554056
switch (superIsolation) {
40564057
case ActorIsolation::Unspecified:
40574058
case ActorIsolation::Nonisolated:
4058-
return false;
4059+
downgradeToWarning = true;
4060+
break;
40594061

40604062
case ActorIsolation::ActorInstance:
40614063
// This is an error that will be diagnosed later. Ignore it here.
@@ -4079,7 +4081,8 @@ static bool checkClassGlobalActorIsolation(
40794081

40804082
// Complain about the mismatch.
40814083
classDecl->diagnose(diag::actor_isolation_superclass_mismatch, isolation,
4082-
classDecl, superIsolation, superclassDecl);
4084+
classDecl, superIsolation, superclassDecl)
4085+
.warnUntilSwiftVersionIf(downgradeToWarning, 6);
40834086
return true;
40844087
}
40854088

test/ClangImporter/objc_async.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ class BarFrame: PictureFrame {
298298
@available(SwiftStdlib 5.5, *)
299299
@SomeGlobalActor
300300
class BazFrame: NotIsolatedPictureFrame {
301+
// expected-warning@-1 {{global actor 'SomeGlobalActor'-isolated class 'BazFrame' has different actor isolation from nonisolated superclass 'NotIsolatedPictureFrame'; this is an error in Swift 6}}
301302
init() {
302303
super.init(size: 0)
303304
}

test/Concurrency/actor_isolation.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,8 @@ actor Counter {
12631263
class C2 { }
12641264

12651265
@SomeGlobalActor
1266-
class C3: C2 { } // it's okay to add a global actor to a nonisolated class.
1266+
class C3: C2 { }
1267+
// expected-warning@-1 {{global actor 'SomeGlobalActor'-isolated class 'C3' has different actor isolation from nonisolated superclass 'C2'; this is an error in Swift 6}}
12671268

12681269
@GenericGlobalActor<U>
12691270
class GenericSuper<U> { }
@@ -1443,6 +1444,8 @@ class None {
14431444
// try to add inferred isolation while overriding
14441445
@MainActor
14451446
class MA_None1: None {
1447+
// expected-warning@-1 {{main actor-isolated class 'MA_None1' has different actor isolation from nonisolated superclass 'None'; this is an error in Swift 6}}
1448+
14461449
// FIXME: bad note, since the problem is a mismatch in overridden vs inferred isolation; this wont help.
14471450
// expected-note@+1 {{add '@MainActor' to make instance method 'method()' part of global actor 'MainActor'}}
14481451
override func method() {
@@ -1472,6 +1475,8 @@ class None_MADirect: MADirect {
14721475

14731476
@SomeGlobalActor
14741477
class SGA_MADirect: MADirect {
1478+
// expected-warning@-1 {{global actor 'SomeGlobalActor'-isolated class 'SGA_MADirect' has different actor isolation from nonisolated superclass 'MADirect'; this is an error in Swift 6}}
1479+
14751480
// inferred-SomeGlobalActor vs overridden-MainActor = mainactor
14761481
override func method1() { beets_ma() }
14771482

test/Concurrency/global_actor_inference.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,10 @@ class SuperclassWithGlobalActors {
246246
func j() { }
247247
}
248248

249-
@GenericGlobalActor<String> // it's okay to add a global actor to nonisolated
249+
@GenericGlobalActor<String>
250250
class SubclassWithGlobalActors : SuperclassWithGlobalActors {
251+
// expected-warning@-1 {{global actor 'GenericGlobalActor<String>'-isolated class 'SubclassWithGlobalActors' has different actor isolation from nonisolated superclass 'SuperclassWithGlobalActors'; this is an error in Swift 6}}
252+
251253
override func f() { } // okay: inferred to @GenericGlobalActor<Int>
252254

253255
@GenericGlobalActor<String> override func g() { } // expected-error{{global actor 'GenericGlobalActor<String>'-isolated instance method 'g()' has different actor isolation from global actor 'GenericGlobalActor<Int>'-isolated overridden declaration}}

0 commit comments

Comments
 (0)