mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
963 lines
45 KiB
Swift
963 lines
45 KiB
Swift
// RUN: %target-swift-frontend -strict-concurrency=complete -target %target-swift-5.1-abi-triple -parse-as-library -emit-sil -o /dev/null -verify %s -enable-upcoming-feature GlobalActorIsolatedTypesUsability
|
|
// RUN: %target-swift-frontend -strict-concurrency=complete -target %target-swift-5.1-abi-triple -parse-as-library -emit-sil -o /dev/null -verify %s -enable-upcoming-feature GlobalActorIsolatedTypesUsability -enable-upcoming-feature NonisolatedNonsendingByDefault
|
|
|
|
// REQUIRES: concurrency
|
|
// REQUIRES: swift_feature_GlobalActorIsolatedTypesUsability
|
|
// REQUIRES: swift_feature_NonisolatedNonsendingByDefault
|
|
|
|
/*
|
|
This file tests the early features of the flow-sensitive Sendable checking implemented by the TransferNonSendable SIL pass.
|
|
In particular, it tests the behavior of applications that cross isolation domains:
|
|
- non-Sendable values are statically grouped into "regions" of values that may alias or point to each other
|
|
- passing a non-Sendable value to an isolation-crossing call "consumed" the region of that value
|
|
- accessing a non-Sendable value requires its region to have not been consumed
|
|
|
|
All non-Sendable arguments, and "self" for non-Sendable classes, are assumed to be in the same region at the start of
|
|
each function, and that region must be preserved at all times - it cannot be passed to another isolation domain.
|
|
*/
|
|
|
|
class NonSendable { // expected-complete-note 73{{}}
|
|
var x : Any
|
|
var y : Any
|
|
|
|
init() {
|
|
x = 0;
|
|
y = 0;
|
|
}
|
|
|
|
init(_ z : Any) {
|
|
x = z;
|
|
y = z;
|
|
}
|
|
}
|
|
|
|
actor A {
|
|
func run_closure(_ closure : () -> ()) async {
|
|
closure();
|
|
}
|
|
|
|
func foo(_ ns : Any) {}
|
|
|
|
func foo_multi(_ : Any, _ : Any, _ : Any) {}
|
|
|
|
func foo_vararg(_ : Any ...) {}
|
|
}
|
|
|
|
func foo_noniso(_ ns : Any) {}
|
|
|
|
func foo_noniso_multi(_ : Any, _ : Any, _ : Any) {}
|
|
|
|
func foo_noniso_vararg(_ : Any ...) {}
|
|
|
|
var bool : Bool { false }
|
|
|
|
func test_isolation_crossing_sensitivity(a : A) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
|
|
// This call does not consume ns0
|
|
foo_noniso(ns0);
|
|
|
|
// This call consumes ns1
|
|
await a.foo(ns1); // expected-warning {{sending 'ns1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns1' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
print(ns0);
|
|
print(ns1); // expected-note {{access can happen concurrently}}
|
|
}
|
|
|
|
func test_arg_nonconsumable(a : A, ns_arg : NonSendable) async {
|
|
let ns_let = NonSendable();
|
|
|
|
// Safe to consume an rvalue.
|
|
await a.foo(NonSendable()); // expected-complete-warning {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
// Safe to consume an lvalue.
|
|
await a.foo(ns_let); // expected-complete-warning {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
// Not safe to consume an arg.
|
|
await a.foo(ns_arg); // expected-warning {{sending 'ns_arg' risks causing data races}}
|
|
// expected-note @-1 {{sending task-isolated 'ns_arg' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and task-isolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
// Check for no duplicate warnings once self is "consumed"
|
|
await a.foo(NonSendable()); // expected-complete-warning {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
}
|
|
|
|
func test_closure_capture(a : A) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
let ns2 = NonSendable();
|
|
let ns3 = NonSendable();
|
|
|
|
let captures0 = { print(ns0) };
|
|
let captures12 = { print(ns1); print(ns2)};
|
|
|
|
let captures3 = { print(ns3) };
|
|
let captures3indirect = { captures3() };
|
|
|
|
// all lets should still be accessible - no consumed have happened yet
|
|
print(ns0)
|
|
print(ns1)
|
|
print(ns2)
|
|
print(ns3)
|
|
|
|
// this should consume ns0
|
|
await a.run_closure(captures0)
|
|
// expected-warning @-1 {{sending 'captures0' risks causing data races}}
|
|
// expected-note @-2 {{sending 'captures0' to actor-isolated instance method 'run_closure' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type '() -> ()' into actor-isolated context may introduce data races}}
|
|
// expected-complete-note @-2 {{a function type must be marked '@Sendable' to conform to 'Sendable'}}
|
|
|
|
print(ns0) // expected-note {{access can happen concurrently}}
|
|
print(ns1)
|
|
print(ns2)
|
|
print(ns3)
|
|
|
|
// this should consume ns1 and ns2
|
|
await a.run_closure(captures12)
|
|
// expected-warning @-1 {{sending 'captures12' risks causing data races}}
|
|
// expected-note @-2 {{sending 'captures12' to actor-isolated instance method 'run_closure' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type '() -> ()' into actor-isolated context may introduce data races}}
|
|
// expected-complete-note @-2 {{a function type must be marked '@Sendable' to conform to 'Sendable'}}
|
|
|
|
// This only touches ns1/ns2 so we get an error on ns1 since it is first.
|
|
print(ns0)
|
|
print(ns1) // expected-note {{access can happen concurrently}}
|
|
print(ns2)
|
|
print(ns3)
|
|
|
|
// this should consume ns3
|
|
await a.run_closure(captures3indirect)
|
|
// expected-warning @-1 {{sending 'captures3indirect' risks causing data races}}
|
|
// expected-note @-2 {{sending 'captures3indirect' to actor-isolated instance method 'run_closure' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type '() -> ()' into actor-isolated context may introduce data races}}
|
|
// expected-complete-note @-2 {{a function type must be marked '@Sendable' to conform to 'Sendable'}}
|
|
|
|
// This only uses ns3 so we should only emit an error on ns3.
|
|
print(ns0)
|
|
print(ns1)
|
|
print(ns2)
|
|
print(ns3) // expected-note {{access can happen concurrently}}
|
|
}
|
|
|
|
func test_regions(a : A, b : Bool) async {
|
|
// definitely aliases - should be in the same region
|
|
let ns0_0 = NonSendable();
|
|
let ns0_1 = ns0_0;
|
|
|
|
// possibly aliases - should be in the same region
|
|
let ns1_0 = NonSendable();
|
|
var ns1_1 = NonSendable();
|
|
if (b) {
|
|
ns1_1 = ns1_0;
|
|
}
|
|
|
|
// accessible via pointer - should be in the same region
|
|
let ns2_0 = NonSendable();
|
|
let ns2_1 = NonSendable();
|
|
ns2_0.x = ns2_1;
|
|
|
|
// check for each of the above pairs that consuming half of it consumes the other half
|
|
|
|
if (b) {
|
|
await a.foo(ns0_0) // expected-warning {{sending 'ns0_0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns0_0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if (b) {
|
|
print(ns0_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns0_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
} else {
|
|
await a.foo(ns0_1) // expected-warning {{sending 'ns0_1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns0_1' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns0_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns0_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
await a.foo(ns1_0) // expected-warning {{sending 'ns1_0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns1_0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns1_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns1_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
} else {
|
|
await a.foo(ns1_1) // expected-warning {{sending 'ns1_1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns1_1' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns1_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns1_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
await a.foo(ns2_0) // expected-warning {{sending 'ns2_0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns2_0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns2_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns2_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
} else {
|
|
await a.foo(ns2_1) // expected-warning {{sending 'ns2_1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns2_1' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns2_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns2_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
}
|
|
}
|
|
|
|
func test_indirect_regions(a : A, b : Bool) async {
|
|
// in each of the following, nsX_0 and nsX_1 should be in the same region for various reasons
|
|
|
|
// 1 constructed using 0
|
|
let ns0_0 = NonSendable();
|
|
let ns0_1 = NonSendable(NonSendable(ns0_0));
|
|
|
|
// 1 constructed using 0, indirectly
|
|
let ns1_0 = NonSendable();
|
|
let ns1_aux = NonSendable(ns1_0);
|
|
let ns1_1 = NonSendable(ns1_aux);
|
|
|
|
// 1 and 0 constructed with same aux value
|
|
let ns2_aux = NonSendable();
|
|
let ns2_0 = NonSendable(ns2_aux);
|
|
let ns2_1 = NonSendable(ns2_aux);
|
|
|
|
// 0 points to aux, which points to 1
|
|
let ns3_aux = NonSendable();
|
|
let ns3_0 = NonSendable();
|
|
let ns3_1 = NonSendable();
|
|
ns3_0.x = ns3_aux;
|
|
ns3_aux.x = ns3_1;
|
|
|
|
// 1 and 0 point to same aux value
|
|
let ns4_aux = NonSendable();
|
|
let ns4_0 = NonSendable();
|
|
let ns4_1 = NonSendable();
|
|
ns4_0.x = ns4_aux;
|
|
ns4_1.x = ns4_aux;
|
|
|
|
// same aux value points to both 0 and 1
|
|
let ns5_aux = NonSendable();
|
|
let ns5_0 = ns5_aux.x;
|
|
let ns5_1 = ns5_aux.y;
|
|
|
|
// now check for each pair that consuming half of it consumed the other half
|
|
|
|
if (b) {
|
|
await a.foo(ns0_0) // expected-warning {{sending 'ns0_0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns0_0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns0_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns0_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
} else {
|
|
await a.foo(ns0_1) // expected-warning {{sending 'ns0_1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns0_1' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns0_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns0_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
await a.foo(ns1_0) // expected-warning {{sending 'ns1_0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns1_0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns1_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns1_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
} else {
|
|
await a.foo(ns1_1) // expected-warning {{sending 'ns1_1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns1_1' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns1_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns1_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
await a.foo(ns2_0) // expected-warning {{sending 'ns2_0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns2_0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns2_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns2_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
} else {
|
|
await a.foo(ns2_1) // expected-warning {{sending 'ns2_1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns2_1' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns2_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns2_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
await a.foo(ns3_0) // expected-warning {{sending 'ns3_0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns3_0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns3_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns3_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
} else {
|
|
await a.foo(ns3_1) // expected-warning {{sending 'ns3_1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns3_1' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns3_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns3_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
await a.foo(ns4_0) // expected-warning {{sending 'ns4_0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns4_0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns4_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns4_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
} else {
|
|
await a.foo(ns4_1) // expected-warning {{sending 'ns4_1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns4_1' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns4_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns4_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
}
|
|
|
|
if (b) {
|
|
await a.foo(ns5_0) // expected-warning {{sending 'ns5_0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns5_0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'Any' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns5_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns5_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
} else {
|
|
await a.foo(ns5_1) // expected-warning {{sending 'ns5_1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns5_1' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'Any' into actor-isolated context may introduce data races}}
|
|
|
|
if b {
|
|
print(ns5_0) // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
print(ns5_1) // expected-note {{access can happen concurrently}}
|
|
}
|
|
}
|
|
}
|
|
|
|
// class methods in general cannot consume self, check that this is true except for Sendable classes (and actors)
|
|
|
|
class C_NonSendable {
|
|
func bar() {}
|
|
|
|
func bar(a : A) async {
|
|
let captures_self = { self.bar() }
|
|
|
|
// this is not a cross-isolation call, so it should be permitted
|
|
foo_noniso(captures_self)
|
|
|
|
// this is a cross-isolation call that captures non-Sendable self, so it should not be permitted
|
|
await a.foo(captures_self) // expected-warning {{sending 'captures_self' risks causing data races}}
|
|
// expected-note @-1 {{sending task-isolated 'captures_self' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and task-isolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type '() -> ()' into actor-isolated context may introduce data races}}
|
|
// expected-complete-note @-3 {{a function type must be marked '@Sendable' to conform to 'Sendable'}}
|
|
}
|
|
}
|
|
|
|
final class C_Sendable : Sendable {
|
|
func bar() {}
|
|
|
|
func bar(a : A) async {
|
|
let captures_self = { self.bar() }
|
|
|
|
// this is not a cross-isolation call, so it should be permitted
|
|
foo_noniso(captures_self)
|
|
|
|
// this is a cross-isolation, but self is Sendable, so it should be permitted
|
|
await a.foo(captures_self)
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type '() -> ()' into actor-isolated context may introduce data races}}
|
|
// expected-complete-note @-2 {{a function type must be marked '@Sendable' to conform to 'Sendable'}}
|
|
}
|
|
}
|
|
|
|
actor A_Sendable {
|
|
func bar() {}
|
|
|
|
func bar(a : A) async {
|
|
let captures_self = { self.bar() }
|
|
|
|
// This is not a cross-isolation call, so it should be permitted
|
|
foo_noniso(captures_self)
|
|
|
|
// This is a cross-isolation call passing a call that should be treated
|
|
// as isolated to self since it captures self which is isolated to our
|
|
// actor and is non-Sendable. For now, we ban this since we do not
|
|
// support the ability to dynamically invoke the synchronous closure on
|
|
// the specific actor.
|
|
await a.foo(captures_self) // expected-warning {{sending 'captures_self' risks causing data races}}
|
|
// expected-note @-1 {{sending 'self'-isolated 'captures_self' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and 'self'-isolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type '() -> ()' into actor-isolated context may introduce data races}}
|
|
// expected-complete-note @-3 {{a function type must be marked '@Sendable' to conform to 'Sendable'}}
|
|
}
|
|
}
|
|
|
|
func basic_loopiness(a : A, b : Bool) async {
|
|
let ns = NonSendable()
|
|
|
|
while (b) {
|
|
await a.foo(ns) // expected-warning {{sending 'ns' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-note @-2 {{access can happen concurrently}}
|
|
// expected-complete-warning @-3 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
}
|
|
}
|
|
|
|
func basic_loopiness_unsafe(a : A, b : Bool) async {
|
|
var ns0 = NonSendable()
|
|
var ns1 = NonSendable()
|
|
var ns2 = NonSendable()
|
|
var ns3 = NonSendable()
|
|
|
|
//should merge all vars
|
|
while (b) {
|
|
(ns0, ns1, ns2, ns3) = (ns1, ns2, ns3, ns0)
|
|
}
|
|
|
|
await a.foo(ns0) // expected-warning {{sending 'ns0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
await a.foo(ns3) // expected-note {{access can happen concurrently}}
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
}
|
|
|
|
func basic_loopiness_safe(a : A, b : Bool) async {
|
|
var ns0 = NonSendable()
|
|
var ns1 = NonSendable()
|
|
var ns2 = NonSendable()
|
|
var ns3 = NonSendable()
|
|
|
|
//should keep ns0 and ns3 separate
|
|
while (b) {
|
|
(ns0, ns1, ns2, ns3) = (ns1, ns0, ns3, ns2)
|
|
}
|
|
|
|
await a.foo(ns0)
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
await a.foo(ns3)
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
}
|
|
|
|
struct StructBox {
|
|
var contents : NonSendable
|
|
|
|
init() {
|
|
contents = NonSendable()
|
|
}
|
|
}
|
|
|
|
func test_struct_assign_doesnt_merge(a : A, b : Bool) async {
|
|
let ns0 = NonSendable()
|
|
let ns1 = NonSendable()
|
|
|
|
//this should merge ns0 and ns1
|
|
var box = StructBox()
|
|
box.contents = ns0
|
|
box.contents = ns1
|
|
|
|
await a.foo(ns0)
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
await a.foo(ns1)
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
}
|
|
|
|
class ClassBox {
|
|
var contents : NonSendable
|
|
|
|
init() {
|
|
contents = NonSendable()
|
|
}
|
|
}
|
|
|
|
func test_class_assign_merges(a : A, b : Bool) async {
|
|
let ns0 = NonSendable()
|
|
let ns1 = NonSendable()
|
|
|
|
// This should merge ns0 and ns1.
|
|
var box = ClassBox()
|
|
box = ClassBox()
|
|
box.contents = ns0
|
|
box.contents = ns1
|
|
|
|
await a.foo(ns0) // expected-warning {{sending 'ns0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
await a.foo(ns1) // expected-note {{access can happen concurrently}}
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
}
|
|
|
|
func test_stack_assign_doesnt_merge(a : A, b : Bool) async {
|
|
let ns0 = NonSendable()
|
|
let ns1 = NonSendable()
|
|
|
|
//this should NOT merge ns0 and ns1
|
|
var contents : NonSendable
|
|
contents = ns0
|
|
contents = ns1
|
|
|
|
foo_noniso(contents) //must use var to avoid warning
|
|
|
|
await a.foo(ns0)
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
await a.foo(ns1)
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
}
|
|
|
|
func test_stack_assign_and_capture_merges(a : A, b : Bool) async {
|
|
let ns0 = NonSendable()
|
|
let ns1 = NonSendable()
|
|
|
|
//this should NOT merge ns0 and ns1
|
|
var contents = NonSendable()
|
|
|
|
let closure = { print(contents) }
|
|
foo_noniso(closure) //must use let to avoid warning
|
|
|
|
contents = ns0
|
|
contents = ns1
|
|
|
|
await a.foo(ns0) // expected-warning {{sending 'ns0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
await a.foo(ns1) // expected-note {{access can happen concurrently}}
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
}
|
|
|
|
func test_tuple_formation(a : A, i : Int) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
let ns2 = NonSendable();
|
|
let ns3 = NonSendable();
|
|
let ns4 = NonSendable();
|
|
let ns012 = (ns0, ns1, ns2);
|
|
let ns13 = (ns1, ns3);
|
|
|
|
switch (i) {
|
|
case 0:
|
|
await a.foo(ns0) // expected-warning {{sending 'ns0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns0' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if bool {
|
|
foo_noniso(ns0); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns1); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns2); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns3); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns4);
|
|
} else if bool {
|
|
foo_noniso(ns012); // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
foo_noniso(ns13); // expected-note {{access can happen concurrently}}
|
|
}
|
|
case 1:
|
|
await a.foo(ns1) // expected-warning {{sending 'ns1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns1' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if bool {
|
|
foo_noniso(ns0); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns1); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns2); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns3); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns4);
|
|
} else if bool {
|
|
foo_noniso(ns012); // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
foo_noniso(ns13); // expected-note {{access can happen concurrently}}
|
|
}
|
|
case 2:
|
|
await a.foo(ns2) // expected-warning {{sending 'ns2' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns2' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
if bool {
|
|
foo_noniso(ns0); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns1); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns2); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns3); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns4);
|
|
} else if bool {
|
|
foo_noniso(ns012); // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
foo_noniso(ns13); // expected-note {{access can happen concurrently}}
|
|
}
|
|
case 3:
|
|
await a.foo(ns4) // expected-warning {{sending 'ns4' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns4' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
foo_noniso(ns0);
|
|
foo_noniso(ns1);
|
|
foo_noniso(ns2);
|
|
foo_noniso(ns4); // expected-note {{access can happen concurrently}}
|
|
foo_noniso(ns012);
|
|
foo_noniso(ns13);
|
|
case 4:
|
|
await a.foo(ns012) // expected-warning {{sending value of non-Sendable type '(NonSendable, NonSendable, NonSendable)' risks causing data races}}
|
|
// expected-note @-1 {{sending value of non-Sendable type '(NonSendable, NonSendable, NonSendable)' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 3{{passing argument of non-Sendable type '(NonSendable, NonSendable, NonSendable)' into actor-isolated context may introduce data races}}
|
|
|
|
if bool {
|
|
foo_noniso(ns0); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns1); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns2); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns3); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns4);
|
|
} else if bool {
|
|
foo_noniso(ns012); // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
foo_noniso(ns13); // expected-note {{access can happen concurrently}}
|
|
}
|
|
default:
|
|
await a.foo(ns13) // expected-warning {{sending value of non-Sendable type '(NonSendable, NonSendable)' risks causing data races}}
|
|
// expected-note @-1 {{sending value of non-Sendable type '(NonSendable, NonSendable)' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-1 2{{passing argument of non-Sendable type '(NonSendable, NonSendable)' into actor-isolated context may introduce data races}}
|
|
|
|
if bool {
|
|
foo_noniso(ns0); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns1); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns2); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns3); // expected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso(ns4);
|
|
} else if bool {
|
|
foo_noniso(ns012); // expected-note {{access can happen concurrently}}
|
|
} else {
|
|
foo_noniso(ns13); // expected-note {{access can happen concurrently}}
|
|
}
|
|
}
|
|
}
|
|
|
|
func reuse_args_safe(a : A) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
let ns2 = NonSendable();
|
|
|
|
// this should be perfectly legal - arguments are assumed to come from the same region
|
|
await a.foo_multi(ns0, ns0, ns0);
|
|
// expected-complete-warning @-1 3{{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
await a.foo_multi(ns1, ns2, ns1);
|
|
// expected-complete-warning @-1 3{{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
}
|
|
|
|
func one_consume_many_require(a : A) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
let ns2 = NonSendable();
|
|
let ns3 = NonSendable();
|
|
let ns4 = NonSendable();
|
|
|
|
await a.foo_multi(ns0, ns1, ns2);
|
|
// expected-complete-warning @-1 3{{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
// expected-warning @-2 {{sending 'ns0' risks causing data races}}
|
|
// expected-note @-3 {{sending 'ns0' to actor-isolated instance method 'foo_multi' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-warning @-4 {{sending 'ns1' risks causing data races}}
|
|
// expected-note @-5 {{sending 'ns1' to actor-isolated instance method 'foo_multi' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-warning @-6 {{sending 'ns2' risks causing data races}}
|
|
// expected-note @-7 {{sending 'ns2' to actor-isolated instance method 'foo_multi' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
|
|
foo_noniso_multi(ns0, ns3, ns4); // expected-note {{access can happen concurrently}}
|
|
foo_noniso_multi(ns3, ns1, ns4); // expected-note {{access can happen concurrently}}
|
|
foo_noniso_multi(ns4, ns3, ns2); // expected-note {{access can happen concurrently}}
|
|
}
|
|
|
|
func one_consume_one_require(a : A) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
let ns2 = NonSendable();
|
|
|
|
await a.foo_multi(ns0, ns1, ns2);
|
|
// expected-complete-warning @-1 3{{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
// expected-warning @-2 {{sending 'ns0' risks causing data races}}
|
|
// expected-note @-3 {{sending 'ns0' to actor-isolated instance method 'foo_multi' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-warning @-4 {{sending 'ns1' risks causing data races}}
|
|
// expected-note @-5 {{sending 'ns1' to actor-isolated instance method 'foo_multi' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-warning @-6 {{sending 'ns2' risks causing data races}}
|
|
// expected-note @-7 {{sending 'ns2' to actor-isolated instance method 'foo_multi' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
|
|
foo_noniso_multi(ns0, ns1, ns2); // expected-note 3{{access can happen concurrently}}
|
|
}
|
|
|
|
func many_consume_one_require(a : A) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
let ns2 = NonSendable();
|
|
let ns3 = NonSendable();
|
|
let ns4 = NonSendable();
|
|
let ns5 = NonSendable();
|
|
|
|
await a.foo_multi(ns0, ns3, ns3) // expected-warning {{sending 'ns0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns0' to actor-isolated instance method 'foo_multi' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 3{{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
await a.foo_multi(ns4, ns1, ns4) // expected-warning {{sending 'ns1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns1' to actor-isolated instance method 'foo_multi' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 3{{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
await a.foo_multi(ns5, ns5, ns2) // expected-warning {{sending 'ns2' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns2' to actor-isolated instance method 'foo_multi' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 3{{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
foo_noniso_multi(ns0, ns1, ns2); //expected-note 3{{access can happen concurrently}}
|
|
}
|
|
|
|
func many_consume_many_require(a : A) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
let ns2 = NonSendable();
|
|
let ns3 = NonSendable();
|
|
let ns4 = NonSendable();
|
|
let ns5 = NonSendable();
|
|
let ns6 = NonSendable();
|
|
let ns7 = NonSendable();
|
|
|
|
await a.foo_multi(ns0, ns3, ns3) // expected-warning {{sending 'ns0' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns0' to actor-isolated instance method 'foo_multi' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 3{{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
await a.foo_multi(ns4, ns1, ns4) // expected-warning {{sending 'ns1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns1' to actor-isolated instance method 'foo_multi' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 3{{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
await a.foo_multi(ns5, ns5, ns2) // expected-warning {{sending 'ns2' risks causing data races}}
|
|
// expected-note @-1 {{sending 'ns2' to actor-isolated instance method 'foo_multi' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 3{{passing argument of non-Sendable type 'NonSendable' into actor-isolated context may introduce data races}}
|
|
|
|
foo_noniso_multi(ns0, ns6, ns7); // expected-note {{access can happen concurrently}}
|
|
foo_noniso_multi(ns6, ns1, ns7); // expected-note {{access can happen concurrently}}
|
|
foo_noniso_multi(ns7, ns6, ns2); // expected-note {{access can happen concurrently}}
|
|
}
|
|
|
|
|
|
func reuse_args_safe_vararg(a : A) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
let ns2 = NonSendable();
|
|
|
|
// this should be perfectly legal - arguments are assumed to come from the same region
|
|
await a.foo_vararg(ns0, ns0, ns0);
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type 'Any...' into actor-isolated context may introduce data races}}
|
|
await a.foo_vararg(ns1, ns2, ns1);
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type 'Any...' into actor-isolated context may introduce data races}}
|
|
}
|
|
|
|
|
|
// The varargs tests are currently disabled because they fail on macos.
|
|
// TODO: fix handling of Array initialization in the SendNonSenable pass
|
|
|
|
/*
|
|
func one_consume_many_require_varag(a : A) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
let ns2 = NonSendable();
|
|
let ns3 = NonSendable();
|
|
let ns4 = NonSendable();
|
|
|
|
// TODO: find a way to make the type used in the diagnostic more specific than the signature type
|
|
await a.foo_vararg(ns0, ns1, ns2);
|
|
// xxpected-warning @-1 {{sending value of non-Sendable type 'Any...' risks causing data races}}
|
|
// xxpected-note @-2 {{sending value of non-Sendable type 'Any...' to actor-isolated instance method 'foo_vararg' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// xxpected-complete-warning @-2 {{passing argument of non-Sendable type 'Any...' into actor-isolated context may introduce data races}}
|
|
|
|
if bool {
|
|
foo_noniso_vararg(ns0, ns3, ns4); // xxpected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso_vararg(ns3, ns1, ns4); // xxpected-note {{access can happen concurrently}}
|
|
} else {
|
|
foo_noniso_vararg(ns4, ns3, ns2); // xxpected-note {{access can happen concurrently}}
|
|
}
|
|
}
|
|
|
|
func one_consume_one_require_vararg(a : A) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
let ns2 = NonSendable();
|
|
|
|
await a.foo_vararg(ns0, ns1, ns2);
|
|
// xxpected-warning @-1 {{sending value of non-Sendable type 'Any...' risks causing data races}}
|
|
// xxpected-note @-2 {{sending value of non-Sendable type 'Any...' to actor-isolated instance method 'foo_vararg' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// xxpected-complete-warning @-2 {{passing argument of non-Sendable type 'Any...' into actor-isolated context may introduce data races}}
|
|
|
|
foo_noniso_vararg(ns0, ns1, ns2); // xxpected-note 1{{access can happen concurrently}}
|
|
}
|
|
|
|
func many_consume_one_require_vararg(a : A) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
let ns2 = NonSendable();
|
|
let ns3 = NonSendable();
|
|
let ns4 = NonSendable();
|
|
let ns5 = NonSendable();
|
|
|
|
await a.foo_vararg(ns0, ns3, ns3)
|
|
// xxpected-warning @-1 {{sending value of non-Sendable type 'Any...' risks causing data races}}
|
|
// xxpected-note @-2 {{sending value of non-Sendable type 'Any...' to actor-isolated instance method 'foo_vararg' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// xxpected-complete-warning @-2 {{passing argument of non-Sendable type 'Any...' into actor-isolated context may introduce data races}}
|
|
await a.foo_vararg(ns4, ns1, ns4)
|
|
// xxpected-warning @-1 {{sending value of non-Sendable type 'Any...' risks causing data races}}
|
|
// xxpected-note @-2 {{sending value of non-Sendable type 'Any...' to actor-isolated instance method 'foo_vararg' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// xxpected-complete-warning @-2 {{passing argument of non-Sendable type 'Any...' into actor-isolated context may introduce data races}}
|
|
await a.foo_vararg(ns5, ns5, ns2)
|
|
// xxpected-warning @-1 {{sending value of non-Sendable type 'Any...' risks causing data races}}
|
|
// xxpected-note @-2 {{sending value of non-Sendable type 'Any...' to actor-isolated instance method 'foo_vararg' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// xxpected-complete-warning @-2 {{passing argument of non-Sendable type 'Any...' into actor-isolated context may introduce data races}}
|
|
|
|
foo_noniso_vararg(ns0, ns1, ns2); // xxpected-note 3{{access can happen concurrently}}
|
|
}
|
|
|
|
func many_consume_many_require_vararg(a : A) async {
|
|
let ns0 = NonSendable();
|
|
let ns1 = NonSendable();
|
|
let ns2 = NonSendable();
|
|
let ns3 = NonSendable();
|
|
let ns4 = NonSendable();
|
|
let ns5 = NonSendable();
|
|
let ns6 = NonSendable();
|
|
let ns7 = NonSendable();
|
|
|
|
await a.foo_vararg(ns0, ns3, ns3)
|
|
// xxpected-warning @-1 {{sending value of non-Sendable type 'Any...' risks causing data races}}
|
|
// xxpected-note @-2 {{sending value of non-Sendable type 'Any...' to actor-isolated instance method 'foo_vararg' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// xxpected-complete-warning @-2 {{passing argument of non-Sendable type 'Any...' into actor-isolated context may introduce data races}}
|
|
await a.foo_vararg(ns4, ns1, ns4)
|
|
// xxpected-warning @-1 {{sending value of non-Sendable type 'Any...' risks causing data races}}
|
|
// xxpected-note @-2 {{sending value of non-Sendable type 'Any...' to actor-isolated instance method 'foo_vararg' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// xxpected-complete-warning @-2 {{passing argument of non-Sendable type 'Any...' into actor-isolated context may introduce data races}}
|
|
await a.foo_vararg(ns5, ns5, ns2)
|
|
// xxpected-warning @-1 {{sending value of non-Sendable type 'Any...' risks causing data races}}
|
|
// xxpected-note @-2 {{sending value of non-Sendable type 'Any...' to actor-isolated instance method 'foo_vararg' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// xxpected-complete-warning @-2 {{passing argument of non-Sendable type 'Any...' into actor-isolated context may introduce data races}}
|
|
|
|
if bool {
|
|
foo_noniso_vararg(ns0, ns6, ns7); // xxpected-note {{access can happen concurrently}}
|
|
} else if bool {
|
|
foo_noniso_vararg(ns6, ns1, ns7); // xxpected-note {{access can happen concurrently}}
|
|
} else {
|
|
foo_noniso_vararg(ns7, ns6, ns2); // xxpected-note {{access can happen concurrently}}
|
|
}
|
|
}
|
|
*/
|
|
|
|
enum E { // expected-complete-note {{consider making enum 'E' conform to the 'Sendable' protocol}}
|
|
case E1(NonSendable)
|
|
case E2(NonSendable)
|
|
case E3(NonSendable)
|
|
}
|
|
|
|
func enum_test(a : A) async {
|
|
let e1 = E.E1(NonSendable())
|
|
let e2 = E.E2(NonSendable())
|
|
let e3 = E.E3(NonSendable())
|
|
let e4 = E.E1(NonSendable())
|
|
|
|
switch (e1) {
|
|
|
|
//this case merges e1 and e2
|
|
case let .E1(ns1):
|
|
switch (e2) {
|
|
case let .E2(ns2):
|
|
ns1.x = ns2.x
|
|
default: ()
|
|
}
|
|
|
|
//this case consumes e3
|
|
case .E2:
|
|
switch (e3) {
|
|
case let .E3(ns3):
|
|
await a.foo(ns3.x) // expected-warning {{sending value of non-Sendable type 'Any' risks causing data races}}
|
|
// expected-note @-1 {{sending value of non-Sendable type 'Any' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-1 {{passing argument of non-Sendable type 'Any' into actor-isolated context may introduce data races}}
|
|
default: ()
|
|
}
|
|
|
|
//this case does nothing
|
|
case .E3:
|
|
foo_noniso(e4);
|
|
}
|
|
|
|
await a.foo(e1); // expected-warning {{sending 'e1' risks causing data races}}
|
|
// expected-note @-1 {{sending 'e1' to actor-isolated instance method 'foo' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
// expected-complete-warning @-2 {{passing argument of non-Sendable type 'E' into actor-isolated context may introduce data races}}
|
|
foo_noniso(e2); // expected-note {{access can happen concurrently}}
|
|
foo_noniso(e3); // expected-note {{access can happen concurrently}}
|
|
foo_noniso(e4);
|
|
}
|