Skip to content

Commit 20b98fe

Browse files
authored
Merge pull request #79575 from AdamCmiel/curried_thunk_actor_isolation
[Sema] Permit dot reference with isolation change without call
2 parents f800fdf + 939aaa9 commit 20b98fe

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

test/Concurrency/actor_isolation.swift

+41
Original file line numberDiff line numberDiff line change
@@ -1723,3 +1723,44 @@ class InferIsolationViaOverride: SuperWithIsolatedMethod {
17231723
// expected-error@-1 {{call to main actor-isolated instance method 'isolatedMethod()' in a synchronous nonisolated context}}
17241724
}
17251725
}
1726+
1727+
struct ReferenceSelfDotMethods {
1728+
@MainActor
1729+
func mainActorAffinedFunction() {}
1730+
1731+
nonisolated
1732+
private func testCurry() -> (Self) -> (@MainActor () -> Void) {
1733+
let functionRef = Self.mainActorAffinedFunction
1734+
// warning goes away with InferSendableFromCaptures, see actor_isolation_swift6.swift
1735+
return functionRef // expected-warning {{converting non-sendable function value to '@MainActor @Sendable () -> Void' may introduce data races}}
1736+
}
1737+
1738+
@MainActor
1739+
private func callOnMainActorOk() {
1740+
let mainActorAffinedClosure = testCurry()(self)
1741+
mainActorAffinedClosure()
1742+
}
1743+
1744+
nonisolated
1745+
private func nonisolatedCallErrors() {
1746+
let mainActorAffinedClosure = testCurry()(self)
1747+
// expected-note@-1 {{calls to let 'mainActorAffinedClosure' from outside of its actor context are implicitly asynchronous}}
1748+
mainActorAffinedClosure()
1749+
// expected-error@-1 {{call to main actor-isolated let 'mainActorAffinedClosure' in a synchronous nonisolated context}}
1750+
}
1751+
}
1752+
1753+
actor UserDefinedActorSelfDotMethod {
1754+
func actorAffinedFunc() {} // expected-note {{calls to instance method 'actorAffinedFunc()' from outside of its actor context are implicitly asynchronous}}
1755+
1756+
// Unfortunately we can't express the desired isolation of this returned closure statically to
1757+
// be able to call it on the desired actor. This may be possible with the acceptance of
1758+
// https://forums.swift.org/t/closure-isolation-control/70378 but I think we need more expressivity
1759+
// in the type system to express this sort of curry.
1760+
nonisolated
1761+
private func testCurry() -> (UserDefinedActorSelfDotMethod) -> (@isolated(any) () -> Void) {
1762+
let functionRef = Self.actorAffinedFunc // expected-error {{call to actor-isolated instance method 'actorAffinedFunc()' in a synchronous nonisolated context}}
1763+
// error message changes with InferSendabaleFromCaptures - see actor_isolation_swift6.swift
1764+
return functionRef // expected-error {{cannot convert return expression of type '(isolated Self) -> () -> ()' to return type '(UserDefinedActorSelfDotMethod) -> @isolated(any) () -> Void'}}
1765+
}
1766+
}

test/Concurrency/actor_isolation_swift6.swift

+39
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,42 @@ nonisolated func accessAcrossActors() {
9595
// expected-error@+1 {{main actor-isolated static property 'shared' can not be referenced from a nonisolated context}}
9696
let _ = MainActorIsolated.shared
9797
}
98+
99+
struct ReferenceSelfDotMethods {
100+
@MainActor
101+
func mainActorAffinedFunction() {}
102+
103+
nonisolated
104+
private func testCurry() -> (Self) -> (@MainActor () -> Void) {
105+
let functionRef = Self.mainActorAffinedFunction
106+
return functionRef
107+
}
108+
109+
@MainActor
110+
private func callOnMainActorOk() {
111+
let mainActorAffinedClosure = testCurry()(self)
112+
mainActorAffinedClosure()
113+
}
114+
115+
nonisolated
116+
private func nonisolatedCallErrors() {
117+
let mainActorAffinedClosure = testCurry()(self)
118+
// expected-note@-1 {{calls to let 'mainActorAffinedClosure' from outside of its actor context are implicitly asynchronous}}
119+
mainActorAffinedClosure()
120+
// expected-error@-1 {{call to main actor-isolated let 'mainActorAffinedClosure' in a synchronous nonisolated context}}
121+
}
122+
}
123+
124+
actor UserDefinedActorSelfDotMethod {
125+
func actorAffinedFunc() {} // expected-note {{calls to instance method 'actorAffinedFunc()' from outside of its actor context are implicitly asynchronous}}
126+
127+
// Unfortunately we can't express the desired isolation of this returned closure statically to
128+
// be able to call it on the desired actor. This may be possible with the acceptance of
129+
// https://forums.swift.org/t/closure-isolation-control/70378 but I think we need more expressivity
130+
// in the type system to express this sort of curry.
131+
nonisolated
132+
private func testCurry() -> (UserDefinedActorSelfDotMethod) -> (@isolated(any) () -> Void) {
133+
let functionRef = Self.actorAffinedFunc // expected-error {{call to actor-isolated instance method 'actorAffinedFunc()' in a synchronous nonisolated context}}
134+
return functionRef // expected-error {{cannot convert return expression of type '@Sendable (isolated Self) -> @Sendable () -> ()' to return type '(UserDefinedActorSelfDotMethod) -> @isolated(any) () -> Void'}}
135+
}
136+
}

0 commit comments

Comments
 (0)