Skip to content

Commit bd41510

Browse files
authored
Merge pull request #73633 from hborla/6.0-global-actor-usability
[6.0][Concurrency] Un-gate implicit `nonisolated` access to struct vars and isolated subclassing.
2 parents 4d63543 + f10baa6 commit bd41510

File tree

6 files changed

+35
-27
lines changed

6 files changed

+35
-27
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -512,16 +512,14 @@ static bool varIsSafeAcrossActors(const ModuleDecl *fromModule,
512512

513513
if (!var->isLet()) {
514514
ASTContext &ctx = var->getASTContext();
515-
if (ctx.LangOpts.hasFeature(Feature::GlobalActorIsolatedTypesUsability)) {
516-
// A mutable storage of a value type accessed from within the module is
517-
// okay.
518-
if (dyn_cast_or_null<StructDecl>(var->getDeclContext()->getAsDecl()) &&
519-
!var->isStatic() &&
520-
var->hasStorage() &&
521-
var->getTypeInContext()->isSendableType() &&
522-
accessWithinModule) {
523-
return true;
524-
}
515+
// A mutable storage of a value type accessed from within the module is
516+
// okay.
517+
if (dyn_cast_or_null<StructDecl>(var->getDeclContext()->getAsDecl()) &&
518+
!var->isStatic() &&
519+
var->hasStorage() &&
520+
var->getTypeInContext()->isSendableType() &&
521+
accessWithinModule) {
522+
return true;
525523
}
526524
// Otherwise, must be immutable.
527525
return false;
@@ -4805,9 +4803,9 @@ static bool checkClassGlobalActorIsolation(
48054803
switch (superIsolation) {
48064804
case ActorIsolation::Unspecified:
48074805
case ActorIsolation::Nonisolated:
4808-
case ActorIsolation::NonisolatedUnsafe:
4809-
downgradeToWarning = true;
4810-
break;
4806+
case ActorIsolation::NonisolatedUnsafe: {
4807+
return false;
4808+
}
48114809

48124810
case ActorIsolation::Erased:
48134811
llvm_unreachable("class cannot have erased isolation");
@@ -6046,6 +6044,13 @@ ProtocolConformance *swift::deriveImplicitSendableConformance(
60466044
inheritedConformance.getConcrete());
60476045
}
60486046
}
6047+
6048+
// Classes that add global actor isolation to non-Sendable
6049+
// superclasses cannot be 'Sendable'.
6050+
auto superclassDecl = classDecl->getSuperclassDecl();
6051+
if (nominal->getGlobalActorAttr() && !superclassDecl->isNSObject()) {
6052+
return nullptr;
6053+
}
60496054
}
60506055
}
60516056

test/ClangImporter/objc_async.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +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 the Swift 6 language mode}}
301+
// expected-note@-1 2 {{class 'BazFrame' does not conform to the 'Sendable' protocol}}
302302
init() {
303303
super.init(size: 0)
304304
}
@@ -322,10 +322,12 @@ func check() async {
322322
_ = await BarFrame()
323323
_ = await FooFrame()
324324
_ = await BazFrame()
325+
// expected-warning@-1 {{non-sendable type 'BazFrame' returned by call to global actor 'SomeGlobalActor'-isolated function cannot cross actor boundary; this is an error in the Swift 6 language mode}}
325326

326327
_ = await BarFrame(size: 0)
327328
_ = await FooFrame(size: 0)
328329
_ = await BazFrame(size: 0)
330+
// expected-warning@-1 {{non-sendable type 'BazFrame' returned by call to global actor 'SomeGlobalActor'-isolated function cannot cross actor boundary; this is an error in the Swift 6 language mode}}
329331
}
330332

331333
@available(SwiftStdlib 5.5, *)

test/Concurrency/actor_isolation.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,8 +1282,14 @@ actor Counter {
12821282
class C2 { }
12831283

12841284
@SomeGlobalActor
1285-
class C3: C2 { }
1286-
// expected-warning@-1 {{global actor 'SomeGlobalActor'-isolated class 'C3' has different actor isolation from nonisolated superclass 'C2'; this is an error in the Swift 6 language mode}}
1285+
class C3: C2 { // expected-note {{class 'C3' does not conform to the 'Sendable' protocol}}
1286+
func requireSendableSelf() {
1287+
Task.detached {
1288+
_ = self
1289+
// expected-warning@-1 {{capture of 'self' with non-sendable type 'C3' in a `@Sendable` closure; this is an error in the Swift 6 language mode}}
1290+
}
1291+
}
1292+
}
12871293

12881294
@GenericGlobalActor<U>
12891295
class GenericSuper<U> { }
@@ -1463,7 +1469,6 @@ class None {
14631469
// try to add inferred isolation while overriding
14641470
@MainActor
14651471
class MA_None1: None {
1466-
// expected-warning@-1 {{main actor-isolated class 'MA_None1' has different actor isolation from nonisolated superclass 'None'; this is an error in the Swift 6 language mode}}
14671472

14681473
// FIXME: bad note, since the problem is a mismatch in overridden vs inferred isolation; this wont help.
14691474
// expected-note@+1 {{add '@MainActor' to make instance method 'method()' part of global actor 'MainActor'}}
@@ -1494,7 +1499,6 @@ class None_MADirect: MADirect {
14941499

14951500
@SomeGlobalActor
14961501
class SGA_MADirect: MADirect {
1497-
// expected-warning@-1 {{global actor 'SomeGlobalActor'-isolated class 'SGA_MADirect' has different actor isolation from nonisolated superclass 'MADirect'; this is an error in the Swift 6 language mode}}
14981502

14991503
// inferred-SomeGlobalActor vs overridden-MainActor = mainactor
15001504
override func method1() { beets_ma() }

test/Concurrency/global_actor_inference.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,6 @@ class SuperclassWithGlobalActors {
248248

249249
@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 the Swift 6 language mode}}
252-
253251
override func f() { } // okay: inferred to @GenericGlobalActor<Int>
254252

255253
@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}}

test/Concurrency/sendable_checking.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ func testConversionsAndSendable(a: MyActor, s: any Sendable, f: @Sendable () ->
239239

240240
@available(SwiftStdlib 5.1, *)
241241
final class NonSendable {
242-
// expected-note @-1 3 {{class 'NonSendable' does not conform to the 'Sendable' protocol}}
242+
// expected-note @-1 4 {{class 'NonSendable' does not conform to the 'Sendable' protocol}}
243243
// TransferNonSendable emits 3 fewer errors here.
244244
// expected-targeted-and-complete-note @-3 5 {{class 'NonSendable' does not conform to the 'Sendable' protocol}}
245245
// expected-complete-and-tns-note @-4 {{class 'NonSendable' does not conform to the 'Sendable' protocol}}
@@ -397,12 +397,13 @@ struct DowngradeForPreconcurrency {
397397
}
398398
}
399399

400-
var x: Int
401-
func createStream() -> AsyncStream<Int> {
402-
AsyncStream<Int> {
400+
var x: NonSendable
401+
func createStream() -> AsyncStream<NonSendable> {
402+
AsyncStream<NonSendable> {
403403
self.x
404404
// expected-warning@-1 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
405405
// expected-note@-2 {{property access is 'async'}}
406+
// expected-warning@-3 {{non-sendable type 'NonSendable' in implicitly asynchronous access to main actor-isolated property 'x' cannot cross actor boundary; this is an error in the Swift 6 language mode}}
406407
}
407408
}
408409
}

test/SILGen/hop_to_executor_async_prop.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -588,10 +588,8 @@ struct Container {
588588
// CHECK: [[SOME_BB]]:
589589
// CHECK: [[DATA_ADDR:%[0-9]+]] = unchecked_take_enum_data_addr [[ACCESS]] : $*Optional<Container>, #Optional.some!enumelt
590590
// CHECK: [[ELEM_ADDR:%[0-9]+]] = struct_element_addr [[DATA_ADDR]] : $*Container, #Container.iso
591-
// CHECK: hop_to_executor {{%[0-9]+}} : $Cat
592591
// CHECK: {{%[0-9]+}} = load [trivial] [[ELEM_ADDR]] : $*Float
593592
// CHECK: hop_to_executor [[GENERIC_EXEC]] :
594-
// CHECK: hop_to_executor [[GENERIC_EXEC]] :
595593
// CHECK: } // end sil function '$s4test9ContainerV10getOrCrashSfyYaFZ'
596594
static func getOrCrash() async -> Float {
597595
return await this!.iso
@@ -628,7 +626,7 @@ struct Container {
628626

629627
@propertyWrapper
630628
struct StateObject<ObjectType> {
631-
@MainActor(unsafe)
629+
@preconcurrency @MainActor
632630
var wrappedValue: ObjectType {
633631
fatalError()
634632
}

0 commit comments

Comments
 (0)