Skip to content

Commit ec48e41

Browse files
authored
Merge pull request #81851 from gottesmm/pr-400c59de66fe5c91648aedb348d84cb7bd8d09f4
[flow-isolation] Allow for initialization of fields of a Global Actor isolated class in its nonisolated inits
2 parents 4777f27 + 501bad5 commit ec48e41

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
@@ -7901,6 +7901,17 @@ ActorReferenceResult ActorReferenceResult::forReference(
79017901
(!actorInstance || actorInstance->isSelf())) {
79027902
auto type = fromDC->mapTypeIntoContext(decl->getInterfaceType());
79037903
if (!type->isSendableType()) {
7904+
// If we have an actor instance and our declIsolation is global actor
7905+
// isolated, but our context isolation is nonisolated... defer to flow
7906+
// isolation if this case passes the additional restrictions required by
7907+
// flow isolation (e.x.: the initializer's nominal type has to be
7908+
// isolated).
7909+
if (actorInstance &&
7910+
declIsolation.isGlobalActor() && contextIsolation.isNonisolated() &&
7911+
checkedByFlowIsolation(fromDC, *actorInstance, decl, declRefLoc, useKind)) {
7912+
return forSameConcurrencyDomain(declIsolation, options);
7913+
}
7914+
79047915
// Treat the decl isolation as 'preconcurrency' to downgrade violations
79057916
// to warnings, because violating Sendable here is accepted by the
79067917
// 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)