Skip to content

Commit 501bad5

Browse files
committed
[flow-isolation] Allow for initialization of fields of a Global Actor isolated class in its nonisolated inits
This just involved loosening some checks in the type checker so we stopped erroring in the type checker and instead deferred to SIL level checks. rdar://131136194
1 parent c287f53 commit 501bad5

File tree

5 files changed

+82
-9
lines changed

5 files changed

+82
-9
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7870,6 +7870,17 @@ ActorReferenceResult ActorReferenceResult::forReference(
78707870
(!actorInstance || actorInstance->isSelf())) {
78717871
auto type = fromDC->mapTypeIntoContext(decl->getInterfaceType());
78727872
if (!type->isSendableType()) {
7873+
// If we have an actor instance and our declIsolation is global actor
7874+
// isolated, but our context isolation is nonisolated... defer to flow
7875+
// isolation if this case passes the additional restrictions required by
7876+
// flow isolation (e.x.: the initializer's nominal type has to be
7877+
// isolated).
7878+
if (actorInstance &&
7879+
declIsolation.isGlobalActor() && contextIsolation.isNonisolated() &&
7880+
checkedByFlowIsolation(fromDC, *actorInstance, decl, declRefLoc, useKind)) {
7881+
return forSameConcurrencyDomain(declIsolation, options);
7882+
}
7883+
78737884
// Treat the decl isolation as 'preconcurrency' to downgrade violations
78747885
// to warnings, because violating Sendable here is accepted by the
78757886
// Swift 5.9 compiler.

test/Concurrency/flow_isolation.swift

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ struct Money {
3232
}
3333
}
3434

35+
actor OtherActorBackingActor { }
36+
37+
@globalActor
38+
struct OtherActor {
39+
static let shared = OtherActorBackingActor()
40+
}
41+
3542
@available(SwiftStdlib 5.1, *)
3643
func takeBob(_ b: Bob) {}
3744

@@ -832,17 +839,78 @@ func testActorWithInitAccessorInit() {
832839

833840
@available(SwiftStdlib 5.1, *)
834841
actor TestNonisolatedUnsafe {
835-
private nonisolated(unsafe) var child: OtherActor!
842+
private nonisolated(unsafe) var child: MyOtherActor!
836843
init() {
837-
child = OtherActor(parent: self)
844+
child = MyOtherActor(parent: self)
838845
}
839846
}
840847

841848
@available(SwiftStdlib 5.1, *)
842-
actor OtherActor {
849+
actor MyOtherActor {
843850
unowned nonisolated let parent: any Actor
844851

845852
init(parent: any Actor) {
846853
self.parent = parent
847854
}
848855
}
856+
857+
func globalActorNonIsolatedInitializerTests() {
858+
@MainActor
859+
class C {
860+
let ns: NonSendableType
861+
862+
nonisolated init() {
863+
self.ns = NonSendableType()
864+
}
865+
866+
nonisolated init(x: NonSendableType) {
867+
self.ns = x
868+
}
869+
870+
nonisolated func doSomething() {}
871+
872+
nonisolated init(x2 x: NonSendableType) {
873+
self.ns = x
874+
doSomething() // expected-note {{after calling instance method 'doSomething()', only nonisolated properties of 'self' can be accessed from this init}}
875+
print(self.ns) // expected-warning {{cannot access property 'ns' here in nonisolated initializer}}
876+
}
877+
}
878+
879+
// Make sure this does not apply in cases where self is not actor isolated.
880+
class D {
881+
@MainActor let ns: NonSendableType // expected-note {{mutation of this property is only permitted within the actor}}
882+
883+
nonisolated init() {
884+
self.ns = NonSendableType() // expected-warning {{main actor-isolated property 'ns' can not be mutated from a nonisolated context}}
885+
}
886+
}
887+
888+
actor A {
889+
@MainActor let ns: NonSendableType
890+
891+
init() {
892+
self.ns = NonSendableType()
893+
}
894+
}
895+
896+
@MainActor
897+
class C2 {
898+
@OtherActor let ns: NonSendableType
899+
900+
nonisolated init() {
901+
self.ns = NonSendableType()
902+
}
903+
904+
nonisolated init(_ x: NonSendableType) {
905+
self.ns = x
906+
}
907+
908+
nonisolated func doSomething() {}
909+
910+
nonisolated init(x2 x: NonSendableType) {
911+
self.ns = x
912+
doSomething() // expected-note {{after calling instance method 'doSomething()', only nonisolated properties of 'self' can be accessed from this init}}
913+
print(self.ns) // expected-warning {{cannot access property 'ns' here in nonisolated initializer}}
914+
}
915+
}
916+
}

test/Concurrency/global_actor_inference.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,13 +336,11 @@ struct WrapperOnActor<Wrapped: Sendable> {
336336
public struct WrapperOnMainActor<Wrapped> {
337337
// Make sure inference of @MainActor on wrappedValue doesn't crash.
338338

339-
// expected-note@+1 {{mutation of this property is only permitted within the actor}}
340339
public var wrappedValue: Wrapped
341340

342341
public var accessCount: Int
343342

344343
nonisolated public init(wrappedValue: Wrapped) {
345-
// expected-warning@+1 {{main actor-isolated property 'wrappedValue' can not be mutated from a nonisolated context; this is an error in the Swift 6 language mode}}
346344
self.wrappedValue = wrappedValue
347345
}
348346
}

test/Concurrency/global_actor_inference_swift6.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,11 @@ struct WrapperOnActor<Wrapped: Sendable> {
6767
public struct WrapperOnMainActor<Wrapped> {
6868
// Make sure inference of @MainActor on wrappedValue doesn't crash.
6969

70-
// expected-note@+1 {{mutation of this property is only permitted within the actor}}
7170
public var wrappedValue: Wrapped // expected-note {{property declared here}}
7271

7372
public var accessCount: Int
7473

7574
nonisolated public init(wrappedValue: Wrapped) {
76-
// expected-error@+1 {{main actor-isolated property 'wrappedValue' can not be mutated from a nonisolated context}}
7775
self.wrappedValue = wrappedValue
7876
}
7977
}

test/Concurrency/nonisolated_rules.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,8 @@ nonisolated struct NonisolatedStruct: GloballyIsolated {
7272
}
7373

7474
struct Nested: GloballyIsolated {
75-
// expected-note@+1 {{mutation of this property is only permitted within the actor}}
7675
var z: NonSendable
7776
nonisolated init(z: NonSendable) {
78-
// expected-error@+1 {{main actor-isolated property 'z' can not be mutated from a nonisolated context}}
7977
self.z = z
8078
}
8179
}

0 commit comments

Comments
 (0)