Files
swift-mirror/test/Concurrency/transfernonsendable_functionsubtyping.swift
Michael Gottesman a6edf4fb90 [rbi] Convert all rbi tests to run also in NonisolatedNonsendingByDefault.
Going to update the tests in the next commit. This just makes it easier to
review.
2025-07-02 12:13:37 -07:00

117 lines
6.9 KiB
Swift

// RUN: %target-typecheck-verify-swift -swift-version 6
// RUN: %target-typecheck-verify-swift -swift-version 6 -enable-upcoming-feature NonisolatedNonsendingByDefault
// READ THIS! This file only contains tests that validate that the relevant
// function subtyping rules for sending work. Please do not put other tests in
// the file!
// REQUIRES: concurrency
// REQUIRES: asserts
// REQUIRES: swift_feature_NonisolatedNonsendingByDefault
////////////////////////
// MARK: Declarations //
////////////////////////
class NonSendableKlass {}
protocol ProtocolWithSendingReqs {
func sendingResult() -> sending NonSendableKlass // expected-note {{}}
func nonSendingParam(_ x: NonSendableKlass) // expected-note {{}}
}
protocol ProtocolWithMixedReqs {
func nonSendingParamAndSendingResult(_ x: NonSendableKlass) -> sending NonSendableKlass // expected-note 4{{}}
}
/////////////////////////////////
// MARK: Normal Function Tests //
/////////////////////////////////
func functionWithSendingResult() -> sending NonSendableKlass { fatalError() }
func functionWithoutSendingResult() -> NonSendableKlass { fatalError() }
func functionWithSendingParameter(_ x: sending NonSendableKlass) { fatalError() }
func functionWithoutSendingParameter(_ x: NonSendableKlass) { fatalError() }
func takeFnWithSendingResult(_ fn: () -> sending NonSendableKlass) {}
func takeFnWithoutSendingResult(_ fn: () -> NonSendableKlass) {}
func takeFnWithSendingParam(_ fn: (sending NonSendableKlass) -> ()) {}
func takeFnWithoutSendingParam(_ fn: (NonSendableKlass) -> ()) {}
func testFunctionMatching() {
let _: (NonSendableKlass) -> () = functionWithSendingParameter
// expected-error @-1 {{converting a value of type '@Sendable (sending NonSendableKlass) -> ()' to type '(NonSendableKlass) -> ()' risks causing data races}}
// expected-note @-2 {{converting a function typed value with a sending parameter to one without risks allowing actor-isolated values to escape their isolation domain as an argument to an invocation of value}}
let _: (sending NonSendableKlass) -> () = functionWithSendingParameter
let _: (NonSendableKlass) -> () = functionWithoutSendingParameter
let _: (sending NonSendableKlass) -> () = functionWithoutSendingParameter
takeFnWithSendingParam(functionWithSendingParameter)
takeFnWithoutSendingParam(functionWithSendingParameter)
// expected-error @-1 {{converting a value of type '@Sendable (sending NonSendableKlass) -> ()' to type '(NonSendableKlass) -> ()' risks causing data races}}
// expected-note @-2 {{converting a function typed value with a sending parameter to one without risks allowing actor-isolated values to escape their isolation domain as an argument to an invocation of value}}
takeFnWithSendingParam(functionWithoutSendingParameter)
takeFnWithoutSendingParam(functionWithoutSendingParameter)
}
func testReturnValueMatching() {
let _: () -> NonSendableKlass = functionWithSendingResult
let _: () -> sending NonSendableKlass = functionWithSendingResult
let _: () -> NonSendableKlass = functionWithoutSendingResult
let _: () -> sending NonSendableKlass = functionWithoutSendingResult
// expected-error @-1 {{converting a value of type '@Sendable () -> NonSendableKlass' to type '() -> sending NonSendableKlass' risks causing data races}}
// expected-note @-2 {{converting a function typed value without a sending result as one with risks allowing actor-isolated values to escape their isolation domain through a result of an invocation of value}}
takeFnWithSendingResult(functionWithSendingResult)
takeFnWithSendingResult(functionWithoutSendingResult)
// expected-error @-1 {{converting a value of type '@Sendable () -> NonSendableKlass' to type '() -> sending NonSendableKlass' risks causing data races}}
// expected-note @-2 {{converting a function typed value without a sending result as one with risks allowing actor-isolated values to escape their isolation domain through a result of an invocation of value}}
let x: () -> NonSendableKlass = { fatalError() }
takeFnWithSendingResult(x)
// expected-error @-1 {{converting a value of type '() -> NonSendableKlass' to type '() -> sending NonSendableKlass' risks causing data races}}
// expected-note @-2 {{converting a function typed value without a sending result as one with risks allowing actor-isolated values to escape their isolation domain through a result of an invocation of value}}
takeFnWithoutSendingResult(functionWithSendingResult)
takeFnWithoutSendingResult(functionWithoutSendingResult)
takeFnWithoutSendingResult(x)
}
//////////////////////////
// MARK: Protocol Tests //
//////////////////////////
struct MatchSuccess : ProtocolWithSendingReqs, ProtocolWithMixedReqs {
func sendingResult() -> sending NonSendableKlass { fatalError() }
func nonSendingParam(_ x: NonSendableKlass) -> () { fatalError() }
func nonSendingParamAndSendingResult(_ x: NonSendableKlass) -> sending NonSendableKlass { fatalError() }
}
struct FailToMatch : ProtocolWithSendingReqs, ProtocolWithMixedReqs {
// expected-error@-1 {{type 'FailToMatch' does not conform to protocol 'ProtocolWithSendingReqs'}}
// expected-error@-2 {{type 'FailToMatch' does not conform to protocol 'ProtocolWithMixedReqs'}}
// expected-note@-3 {{add stubs for conformance}}
func sendingResult() -> NonSendableKlass { fatalError() }
// expected-note @-1 {{candidate has non-matching type '() -> NonSendableKlass'}}
func nonSendingParam(_ x: sending NonSendableKlass) -> () { fatalError() }
// expected-note @-1 {{candidate has non-matching type '(sending NonSendableKlass) -> ()'}}
func nonSendingParamAndSendingResult(_ x: sending NonSendableKlass) -> NonSendableKlass { fatalError() }
// expected-note @-1 {{candidate has non-matching type '(sending NonSendableKlass) -> NonSendableKlass'}}
}
struct FailToMatch2 : ProtocolWithMixedReqs { // expected-error {{type 'FailToMatch2' does not conform to protocol 'ProtocolWithMixedReqs'}} expected-note {{add stubs for conformance}}
func nonSendingParamAndSendingResult(_ x: sending NonSendableKlass) -> NonSendableKlass { fatalError() }
// expected-note @-1 {{candidate has non-matching type '(sending NonSendableKlass) -> NonSendableKlass'}}
}
struct FailToMatch3 : ProtocolWithMixedReqs { // expected-error {{type 'FailToMatch3' does not conform to protocol 'ProtocolWithMixedReqs'}} expected-note {{add stubs for conformance}}
func nonSendingParamAndSendingResult(_ x: NonSendableKlass) -> NonSendableKlass { fatalError() }
// expected-note @-1 {{candidate has non-matching type '(NonSendableKlass) -> NonSendableKlass'}}
}
struct FailToMatch4 : ProtocolWithMixedReqs { // expected-error {{type 'FailToMatch4' does not conform to protocol 'ProtocolWithMixedReqs'}} expected-note {{add stubs for conformance}}
func nonSendingParamAndSendingResult(_ x: sending NonSendableKlass) -> sending NonSendableKlass { fatalError() }
// expected-note @-1 {{candidate has non-matching type '(sending NonSendableKlass) -> sending NonSendableKlass'}}
}