mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Going to update the tests in the next commit. This just makes it easier to
review.
(cherry picked from commit a6edf4fb90)
408 lines
20 KiB
Swift
408 lines
20 KiB
Swift
// RUN: %empty-directory(%t)
|
|
|
|
// A swift 5 module /without/ concurrency checking
|
|
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/PreconcurrencyUnchecked.swiftmodule -module-name PreconcurrencyUnchecked %S/Inputs/transfernonsendable_preconcurrency_unchecked.swift -target %target-swift-5.1-abi-triple -swift-version 5
|
|
|
|
// A swift 5 module /with/ concurrency checking
|
|
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/PreconcurrencyChecked.swiftmodule -module-name PreconcurrencyChecked %S/Inputs/transfernonsendable_preconcurrency_checked.swift -target %target-swift-5.1-abi-triple -swift-version 5 -strict-concurrency=complete
|
|
|
|
// Test swift 5 with strict concurrency
|
|
// RUN: %target-swift-frontend -swift-version 5 %s -emit-sil -o /dev/null -verify -verify-additional-prefix swift-5- -parse-as-library -I %t -strict-concurrency=complete -target %target-swift-5.1-abi-triple
|
|
|
|
// Test swift 6
|
|
// RUN: %target-swift-frontend -swift-version 6 %s -emit-sil -o /dev/null -verify -verify-additional-prefix swift-6- -parse-as-library -I %t -target %target-swift-5.1-abi-triple
|
|
// RUN: %target-swift-frontend -swift-version 6 %s -emit-sil -o /dev/null -verify -verify-additional-prefix swift-6- -parse-as-library -I %t -target %target-swift-5.1-abi-triple -enable-upcoming-feature NonisolatedNonsendingByDefault
|
|
|
|
// REQUIRES: concurrency
|
|
// REQUIRES: asserts
|
|
// REQUIRES: swift_feature_NonisolatedNonsendingByDefault
|
|
|
|
// README: This test is meant to test the interaction of transfernonsendable,
|
|
// preconcurrency, and transferring. Please only keep such tests in this file.
|
|
|
|
////////////////////////
|
|
// MARK: Declarations //
|
|
////////////////////////
|
|
|
|
@preconcurrency import PreconcurrencyUnchecked
|
|
import PreconcurrencyChecked
|
|
|
|
typealias PreCUncheckedNonSendableKlass = PreconcurrencyUnchecked.NonSendableKlass
|
|
typealias PreCUncheckedExplicitlyNonSendableKlass = PreconcurrencyUnchecked.ExplicitlyNonSendableKlass
|
|
typealias PostCUncheckedNonSendableKlass = PreconcurrencyChecked.NonSendableKlass
|
|
|
|
actor CustomActorInstance {}
|
|
|
|
@globalActor
|
|
struct CustomActor {
|
|
static let shared = CustomActorInstance()
|
|
}
|
|
|
|
func transferToNonIsolated<T>(_ t: T) async {}
|
|
@MainActor func transferToMain<T>(_ t: T) async {}
|
|
@CustomActor func transferToCustom<T>(_ t: T) async {}
|
|
func useValue<T>(_ t: T) {}
|
|
func useValueAsync<T>(_ t: T) async {}
|
|
@MainActor func useValueMain<T>(_ t: T) {}
|
|
@MainActor func mainActorFunction() {}
|
|
|
|
func transferArg<T>(_ t: sending T) {}
|
|
|
|
actor MyActor {}
|
|
func takeClosure(_ x: sending () -> ()) {}
|
|
func takeClosureAndParam<T>(_ x: T, _ y: sending () -> ()) {}
|
|
|
|
struct Pair<T> {
|
|
var lhs: T
|
|
var rhs: T
|
|
}
|
|
|
|
struct PreCUncheckedNonSendableKlassPair {
|
|
var lhs: PreCUncheckedNonSendableKlass
|
|
var rhs: PreCUncheckedNonSendableKlass
|
|
}
|
|
|
|
struct PreCUncheckedExplicitlyNonSendableKlassPair {
|
|
var lhs: PreCUncheckedExplicitlyNonSendableKlass
|
|
var rhs: PreCUncheckedExplicitlyNonSendableKlass
|
|
}
|
|
|
|
struct PostCUncheckedNonSendableKlassPair {
|
|
var lhs: PostCUncheckedNonSendableKlass
|
|
var rhs: PostCUncheckedNonSendableKlass
|
|
}
|
|
|
|
////////////////////////////////////
|
|
// MARK: Use After Transfer Tests //
|
|
////////////////////////////////////
|
|
|
|
// In swift 5, this should be squelched and should emit a warning in swift 6.
|
|
func testPreconcurrencyImplicitlyNonSendable() async {
|
|
let x = PreCUncheckedNonSendableKlass()
|
|
transferArg(x)
|
|
useValue(x)
|
|
}
|
|
|
|
// In swift 5 and swift 6, this should be a warning.
|
|
func testPreconcurrencyExplicitlyNonSendable() async {
|
|
let x = PreCUncheckedExplicitlyNonSendableKlass()
|
|
transferArg(x)
|
|
|
|
// expected-swift-5-warning @-2 {{sending 'x' risks causing data races}}
|
|
// expected-swift-5-note @-3 {{'x' used after being passed as a 'sending' parameter; Later uses could race}}
|
|
// expected-swift-6-warning @-4 {{sending 'x' risks causing data races}}
|
|
// expected-swift-6-note @-5 {{'x' used after being passed as a 'sending' parameter; Later uses could race}}
|
|
useValue(x)
|
|
// expected-swift-5-note @-1 {{access can happen concurrently}}
|
|
// expected-swift-6-note @-2 {{access can happen concurrently}}
|
|
}
|
|
|
|
// In swift 5 this is a warning and in swift 6 this is an error.
|
|
func testNormal() async {
|
|
let x = PostCUncheckedNonSendableKlass()
|
|
transferArg(x)
|
|
// expected-swift-5-warning @-1 {{sending 'x' risks causing data races}}
|
|
// expected-swift-6-error @-2 {{sending 'x' risks causing data races}}
|
|
// expected-swift-5-note @-3 {{'x' used after being passed as a 'sending' parameter; Later uses could race}}
|
|
// expected-swift-6-note @-4 {{'x' used after being passed as a 'sending' parameter; Later uses could race}}
|
|
useValue(x) // expected-swift-5-note {{access can happen concurrently}}
|
|
// expected-swift-6-note @-1 {{access can happen concurrently}}
|
|
}
|
|
|
|
func testOnlyErrorOnExactValue() async {
|
|
let x = PreCUncheckedNonSendableKlass()
|
|
let y = (x, x)
|
|
// We would squelch this if we transferred it directly. Also we error even
|
|
// though we use x later.
|
|
transferArg(y)
|
|
useValue(x)
|
|
}
|
|
|
|
func testNoErrorIfUseInSameRegionLater() async {
|
|
let x = PreCUncheckedNonSendableKlass()
|
|
let y = (x, x)
|
|
// We squelch since we are sending x.
|
|
transferArg(x)
|
|
useValue(y)
|
|
}
|
|
|
|
////////////////////////////////
|
|
// MARK: Never Transfer Tests //
|
|
////////////////////////////////
|
|
|
|
func testNeverTransfer(_ x: PreCUncheckedNonSendableKlass) async {
|
|
transferArg(x)
|
|
}
|
|
|
|
func testNeverTransferExplicit(_ x: PreCUncheckedExplicitlyNonSendableKlass) async {
|
|
transferArg(x)
|
|
// expected-swift-5-warning @-1 {{sending 'x' risks causing data races}}
|
|
// expected-swift-5-note @-2 {{task-isolated 'x' is passed as a 'sending' parameter; Uses in callee may race with later task-isolated uses}}
|
|
// expected-swift-6-warning @-3 {{sending 'x' risks causing data races}}
|
|
// expected-swift-6-note @-4 {{task-isolated 'x' is passed as a 'sending' parameter; Uses in callee may race with later task-isolated uses}}
|
|
}
|
|
|
|
func testNeverTransferNormal(_ x: PostCUncheckedNonSendableKlass) async {
|
|
transferArg(x)
|
|
// expected-swift-5-warning @-1 {{sending 'x' risks causing data races}}
|
|
// expected-swift-5-note @-2 {{task-isolated 'x' is passed as a 'sending' parameter; Uses in callee may race with later task-isolated uses}}
|
|
// expected-swift-6-error @-3 {{sending 'x' risks causing data races}}
|
|
// expected-swift-6-note @-4 {{task-isolated 'x' is passed as a 'sending' parameter; Uses in callee may race with later task-isolated uses}}
|
|
}
|
|
|
|
// Inexact match => normal behavior.
|
|
func testNeverTransferInexactMatch(_ x: (PreCUncheckedNonSendableKlass, PreCUncheckedNonSendableKlass)) async {
|
|
transferArg(x)
|
|
}
|
|
|
|
// Inexact match => normal behavior.
|
|
//
|
|
// NOTE: We used to improperly emit an error in swift-6 here despite the fact
|
|
// that we should have emitted a warning. This is because we were not computing
|
|
// diagnostic behavior for tuples. The tuple was viewed as a non-preconcurrency
|
|
// type so we just emitted an error. Now that we properly compute structurally
|
|
// that the tuple contains explicitly non sendable, we emit a warning.
|
|
func testNeverTransferInexactMatchExplicit(_ x: (PreCUncheckedExplicitlyNonSendableKlass, PreCUncheckedExplicitlyNonSendableKlass)) async {
|
|
transferArg(x)
|
|
// expected-swift-5-warning @-1 {{sending 'x' risks causing data races}}
|
|
// expected-swift-5-note @-2 {{task-isolated 'x' is passed as a 'sending' parameter; Uses in callee may race with later task-isolated uses}}
|
|
// expected-swift-6-warning @-3 {{sending 'x' risks causing data races}}
|
|
// expected-swift-6-note @-4 {{task-isolated 'x' is passed as a 'sending' parameter; Uses in callee may race with later task-isolated uses}}
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
// MARK: Never Sendable Closure Tests //
|
|
////////////////////////////////////////
|
|
|
|
func taskIsolatedCaptureInSendingClosureLiteral(_ x: PreCUncheckedNonSendableKlass) {
|
|
Task {
|
|
print(x)
|
|
}
|
|
|
|
takeClosure {
|
|
print(x)
|
|
}
|
|
|
|
takeClosureAndParam(PreCUncheckedNonSendableKlass()) {
|
|
print(x)
|
|
}
|
|
|
|
let y = (x, x)
|
|
Task {
|
|
print(y)
|
|
}
|
|
|
|
let z = (x, y)
|
|
Task {
|
|
print(y, z)
|
|
}
|
|
|
|
let w = PreCUncheckedNonSendableKlassPair(lhs: x, rhs: x)
|
|
Task {
|
|
print(w)
|
|
}
|
|
|
|
let u = Pair(lhs: x, rhs: x)
|
|
Task {
|
|
print(u)
|
|
}
|
|
}
|
|
|
|
extension MyActor {
|
|
func actorIsolatedCaptureInSendingClosureLiteral(_ x: PreCUncheckedNonSendableKlass) {
|
|
Task {
|
|
print(x)
|
|
}
|
|
|
|
takeClosure {
|
|
print(x)
|
|
}
|
|
|
|
takeClosureAndParam(PreCUncheckedNonSendableKlass()) {
|
|
print(x)
|
|
}
|
|
|
|
let y = (x, x)
|
|
Task {
|
|
print(y)
|
|
}
|
|
|
|
let z = (x, y)
|
|
Task {
|
|
print(y, z)
|
|
}
|
|
|
|
let w = PreCUncheckedNonSendableKlassPair(lhs: x, rhs: x)
|
|
Task {
|
|
print(w)
|
|
}
|
|
|
|
let u = Pair(lhs: x, rhs: x)
|
|
Task {
|
|
print(u)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Since this is unchecked by marking as explicitly non-Sendable, we respect
|
|
// what the importing user wanted and change swift 6 to warn and swift 5 to
|
|
// warn.
|
|
func taskIsolatedCaptureInSendingClosureLiteral(_ x: PreCUncheckedExplicitlyNonSendableKlass) {
|
|
Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(x) // expected-note {{closure captures 'x' which is accessible to code in the current task}}
|
|
}
|
|
|
|
takeClosure { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(x) // expected-note {{closure captures 'x' which is accessible to code in the current task}}
|
|
}
|
|
|
|
takeClosureAndParam(PreCUncheckedExplicitlyNonSendableKlass()) { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(x) // expected-note {{closure captures 'x' which is accessible to code in the current task}}
|
|
}
|
|
|
|
let y = (x, x)
|
|
Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(y) // expected-note {{closure captures 'y' which is accessible to code in the current task}}
|
|
}
|
|
|
|
let z = (x, y)
|
|
Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(y, z) // expected-note @:11 {{closure captures non-Sendable 'y'}}
|
|
// expected-note @-1:14 {{closure captures non-Sendable 'z'}}
|
|
}
|
|
|
|
let w = PreCUncheckedExplicitlyNonSendableKlassPair(lhs: x, rhs: x)
|
|
Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(w) // expected-note {{closure captures 'w' which is accessible to code in the current task}}
|
|
}
|
|
|
|
let u = Pair(lhs: x, rhs: x)
|
|
Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(u) // expected-note {{closure captures 'u' which is accessible to code in the current task}}
|
|
}
|
|
}
|
|
|
|
extension MyActor {
|
|
func actorIsolatedCaptureInSendingClosureLiteral(_ x: PreCUncheckedExplicitlyNonSendableKlass) {
|
|
Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(x) // expected-note {{closure captures 'self'-isolated 'x'}}
|
|
}
|
|
|
|
takeClosure { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(x) // expected-note {{closure captures 'self'-isolated 'x'}}
|
|
}
|
|
|
|
takeClosureAndParam(PreCUncheckedExplicitlyNonSendableKlass()) { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(x) // expected-note {{closure captures 'self'-isolated 'x'}}
|
|
}
|
|
|
|
let y = (x, x)
|
|
Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(y) // expected-note {{closure captures 'y' which is accessible to 'self'-isolated code}}
|
|
}
|
|
|
|
let z = (x, y)
|
|
Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(y, z) // expected-note @:13 {{closure captures non-Sendable 'y'}}
|
|
// expected-note @-1:16 {{closure captures non-Sendable 'z'}}
|
|
}
|
|
|
|
let w = PreCUncheckedExplicitlyNonSendableKlassPair(lhs: x, rhs: x)
|
|
Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(w) // expected-note {{closure captures 'w' which is accessible to 'self'-isolated code}}
|
|
}
|
|
|
|
let u = Pair(lhs: x, rhs: x)
|
|
Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(u) // expected-note {{closure captures 'u' which is accessible to 'self'-isolated code}}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Since this is a swift 6 class, we emit the full error.
|
|
func taskIsolatedCaptureInSendingClosureLiteral(_ x: PostCUncheckedNonSendableKlass) {
|
|
Task { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(x) // expected-note {{closure captures 'x' which is accessible to code in the current task}}
|
|
}
|
|
|
|
takeClosure { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(x) // expected-note {{closure captures 'x' which is accessible to code in the current task}}
|
|
}
|
|
|
|
takeClosureAndParam(PostCUncheckedNonSendableKlass()) { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(x) // expected-note {{closure captures 'x' which is accessible to code in the current task}}
|
|
}
|
|
|
|
let y = (x, x)
|
|
Task { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(y) // expected-note {{closure captures 'y' which is accessible to code in the current task}}
|
|
}
|
|
|
|
let z = (x, y)
|
|
Task { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(y, z) // expected-note @:11 {{closure captures non-Sendable 'y'}}
|
|
// expected-note @-1:14 {{closure captures non-Sendable 'z'}}
|
|
}
|
|
|
|
let w = PostCUncheckedNonSendableKlassPair(lhs: x, rhs: x)
|
|
Task { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(w) // expected-note {{closure captures 'w' which is accessible to code in the current task}}
|
|
}
|
|
|
|
let u = Pair(lhs: x, rhs: x)
|
|
Task { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
|
|
print(u) // expected-note {{closure captures 'u' which is accessible to code in the current task}}
|
|
}
|
|
}
|
|
|
|
extension MyActor {
|
|
func actorIsolatedCaptureInSendingClosureLiteral(_ x: PostCUncheckedNonSendableKlass) {
|
|
Task { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(x) // expected-note {{closure captures 'self'-isolated 'x'}}
|
|
}
|
|
|
|
takeClosure { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(x) // expected-note {{closure captures 'self'-isolated 'x'}}
|
|
}
|
|
|
|
takeClosureAndParam(PostCUncheckedNonSendableKlass()) { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(x) // expected-note {{closure captures 'self'-isolated 'x'}}
|
|
}
|
|
|
|
let y = (x, x)
|
|
Task { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(y) // expected-note {{closure captures 'y' which is accessible to 'self'-isolated code}}
|
|
}
|
|
|
|
let z = (x, y)
|
|
Task { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(y, z) // expected-note @:13 {{closure captures non-Sendable 'y'}}
|
|
// expected-note @-1:16 {{closure captures non-Sendable 'z'}}
|
|
}
|
|
|
|
let w = PostCUncheckedNonSendableKlassPair(lhs: x, rhs: x)
|
|
Task { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(w) // expected-note {{closure captures 'w' which is accessible to 'self'-isolated code}}
|
|
}
|
|
|
|
let u = Pair(lhs: x, rhs: x)
|
|
Task { // expected-swift-6-error {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
// expected-swift-5-warning @-1 {{passing closure as a 'sending' parameter risks causing data races between 'self'-isolated code and concurrent execution of the closure}}
|
|
print(u) // expected-note {{closure captures 'u' which is accessible to 'self'-isolated code}}
|
|
}
|
|
}
|
|
}
|