Skip to content

Commit 9773e89

Browse files
authored
Merge pull request #73279 from hborla/actor-nonisolated-let
[Concurrency] Check `varIsSafeAcrossActors` in `getActorIsolationForReference`.
2 parents c936202 + 39c7962 commit 9773e89

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6465,12 +6465,19 @@ static ActorIsolation getActorIsolationForReference(ValueDecl *decl,
64656465
// Fall through to treat initializers like any other declaration.
64666466
}
64676467

6468-
// A 'nonisolated let' within an actor is treated as isolated from the
6469-
// perspective of the referencer.
6468+
// A 'nonisolated let' within an actor is treated as isolated if
6469+
// the access is outside the module or if the property type is not
6470+
// 'Sendable'.
64706471
//
64716472
// FIXME: getActorIsolation(decl) should treat these as isolated.
64726473
// FIXME: Expand this out to local variables?
64736474
if (auto var = dyn_cast<VarDecl>(decl)) {
6475+
auto *fromModule = fromDC->getParentModule();
6476+
ActorReferenceResult::Options options = std::nullopt;
6477+
if (varIsSafeAcrossActors(fromModule, var, declIsolation, options) &&
6478+
var->getTypeInContext()->isSendableType())
6479+
return ActorIsolation::forNonisolated(/*unsafe*/false);
6480+
64746481
if (var->isLet() && isStoredProperty(var) &&
64756482
declIsolation.isNonisolated()) {
64766483
if (auto nominal = var->getDeclContext()->getSelfNominalTypeDecl()) {

test/Concurrency/actor_isolation.swift

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,11 @@ func checkIsolationValueType(_ formance: InferredFromConformance,
156156
_ anno: NoGlobalActorValueType) async {
157157
// these still do need an await in Swift 5
158158
_ = await ext.point // expected-warning {{non-sendable type 'Point' in implicitly asynchronous access to main actor-isolated property 'point' cannot cross actor boundary}}
159-
_ = formance.counter
160159
_ = await anno.point // expected-warning {{non-sendable type 'Point' in implicitly asynchronous access to global actor 'SomeGlobalActor'-isolated property 'point' cannot cross actor boundary}}
161160
// expected-warning@-1 {{non-sendable type 'NoGlobalActorValueType' passed in implicitly asynchronous call to global actor 'SomeGlobalActor'-isolated property 'point' cannot cross actor boundary}}
162-
_ = anno.counter // expected-warning {{non-sendable type 'NoGlobalActorValueType' passed in call to main actor-isolated property 'counter' cannot cross actor boundary}}
161+
162+
_ = formance.counter
163+
_ = anno.counter
163164

164165
// these will always need an await
165166
_ = await (formance as MainCounter).counter // expected-warning {{non-sendable type 'any MainCounter' passed in implicitly asynchronous call to main actor-isolated property 'counter' cannot cross actor boundary}}
@@ -171,7 +172,7 @@ func checkIsolationValueType(_ formance: InferredFromConformance,
171172
}
172173

173174
// expected-warning@+2 {{memberwise initializer for 'NoGlobalActorValueType' cannot be both nonisolated and global actor 'SomeGlobalActor'-isolated; this is an error in the Swift 6 language mode}}
174-
// expected-note@+1 2 {{consider making struct 'NoGlobalActorValueType' conform to the 'Sendable' protocol}}
175+
// expected-note@+1 {{consider making struct 'NoGlobalActorValueType' conform to the 'Sendable' protocol}}
175176
struct NoGlobalActorValueType {
176177
@SomeGlobalActor var point: Point
177178
// expected-note@-1 {{initializer for property 'point' is global actor 'SomeGlobalActor'-isolated}}
@@ -1636,3 +1637,19 @@ nonisolated func accessAcrossActors() {
16361637
// expected-warning@+1 {{main actor-isolated static property 'shared' can not be referenced from a non-isolated context; this is an error in the Swift 6 language mode}}
16371638
let _ = MainActorIsolated.shared
16381639
}
1640+
1641+
@available(SwiftStdlib 5.1, *)
1642+
actor Iterator: AsyncIteratorProtocol {
1643+
init() {}
1644+
func next() throws -> Int? { nil }
1645+
}
1646+
1647+
@available(SwiftStdlib 5.1, *)
1648+
actor SafeMutatingCall {
1649+
private let iterator: Iterator
1650+
1651+
public init() async throws {
1652+
self.iterator = Iterator()
1653+
_ = try await self.iterator.next()
1654+
}
1655+
}

0 commit comments

Comments
 (0)