Skip to content

[Sema] Permit dot reference with isolation change without call #79575

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions test/Concurrency/actor_isolation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1723,3 +1723,44 @@ class InferIsolationViaOverride: SuperWithIsolatedMethod {
// expected-error@-1 {{call to main actor-isolated instance method 'isolatedMethod()' in a synchronous nonisolated context}}
}
}

struct ReferenceSelfDotMethods {
@MainActor
func mainActorAffinedFunction() {}

nonisolated
private func testCurry() -> (Self) -> (@MainActor () -> Void) {
let functionRef = Self.mainActorAffinedFunction
// warning goes away with InferSendableFromCaptures, see actor_isolation_swift6.swift
return functionRef // expected-warning {{converting non-sendable function value to '@MainActor @Sendable () -> Void' may introduce data races}}
}

@MainActor
private func callOnMainActorOk() {
let mainActorAffinedClosure = testCurry()(self)
mainActorAffinedClosure()
}

nonisolated
private func nonisolatedCallErrors() {
let mainActorAffinedClosure = testCurry()(self)
// expected-note@-1 {{calls to let 'mainActorAffinedClosure' from outside of its actor context are implicitly asynchronous}}
mainActorAffinedClosure()
// expected-error@-1 {{call to main actor-isolated let 'mainActorAffinedClosure' in a synchronous nonisolated context}}
}
}

actor UserDefinedActorSelfDotMethod {
func actorAffinedFunc() {} // expected-note {{calls to instance method 'actorAffinedFunc()' from outside of its actor context are implicitly asynchronous}}

// Unfortunately we can't express the desired isolation of this returned closure statically to
// be able to call it on the desired actor. This may be possible with the acceptance of
// https://forums.swift.org/t/closure-isolation-control/70378 but I think we need more expressivity
// in the type system to express this sort of curry.
nonisolated
private func testCurry() -> (UserDefinedActorSelfDotMethod) -> (@isolated(any) () -> Void) {
let functionRef = Self.actorAffinedFunc // expected-error {{call to actor-isolated instance method 'actorAffinedFunc()' in a synchronous nonisolated context}}
// error message changes with InferSendabaleFromCaptures - see actor_isolation_swift6.swift
return functionRef // expected-error {{cannot convert return expression of type '(isolated Self) -> () -> ()' to return type '(UserDefinedActorSelfDotMethod) -> @isolated(any) () -> Void'}}
}
}
39 changes: 39 additions & 0 deletions test/Concurrency/actor_isolation_swift6.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,42 @@ nonisolated func accessAcrossActors() {
// expected-error@+1 {{main actor-isolated static property 'shared' can not be referenced from a nonisolated context}}
let _ = MainActorIsolated.shared
}

struct ReferenceSelfDotMethods {
@MainActor
func mainActorAffinedFunction() {}

nonisolated
private func testCurry() -> (Self) -> (@MainActor () -> Void) {
let functionRef = Self.mainActorAffinedFunction
return functionRef
}

@MainActor
private func callOnMainActorOk() {
let mainActorAffinedClosure = testCurry()(self)
mainActorAffinedClosure()
}

nonisolated
private func nonisolatedCallErrors() {
let mainActorAffinedClosure = testCurry()(self)
// expected-note@-1 {{calls to let 'mainActorAffinedClosure' from outside of its actor context are implicitly asynchronous}}
mainActorAffinedClosure()
// expected-error@-1 {{call to main actor-isolated let 'mainActorAffinedClosure' in a synchronous nonisolated context}}
}
}

actor UserDefinedActorSelfDotMethod {
func actorAffinedFunc() {} // expected-note {{calls to instance method 'actorAffinedFunc()' from outside of its actor context are implicitly asynchronous}}

// Unfortunately we can't express the desired isolation of this returned closure statically to
// be able to call it on the desired actor. This may be possible with the acceptance of
// https://forums.swift.org/t/closure-isolation-control/70378 but I think we need more expressivity
// in the type system to express this sort of curry.
nonisolated
private func testCurry() -> (UserDefinedActorSelfDotMethod) -> (@isolated(any) () -> Void) {
let functionRef = Self.actorAffinedFunc // expected-error {{call to actor-isolated instance method 'actorAffinedFunc()' in a synchronous nonisolated context}}
return functionRef // expected-error {{cannot convert return expression of type '@Sendable (isolated Self) -> @Sendable () -> ()' to return type '(UserDefinedActorSelfDotMethod) -> @isolated(any) () -> Void'}}
}
}