mirror of
https://github.com/apple/swift.git
synced 2026-10-16 16:50:49 +02:00
"Task-isolated" is an internal implementation term that is not meaningful to users. Replace it with the user-facing "code in the current isolation context" formulation throughout region-based isolation diagnostics. Diagnostic definitions in DiagnosticsSIL.def are updated to accept an additional bool parameter for task-isolation and use %select to choose between the actor-isolation string and "code in the current isolation context". Emission sites in SendNonSendable.cpp are updated to pass isTaskIsolated() at each call site. All affected test expectations are updated to match the new output. rdar://178534037
247 lines
9.2 KiB
Swift
247 lines
9.2 KiB
Swift
// RUN: %target-swift-frontend -emit-sil -strict-concurrency=complete -target %target-swift-5.1-abi-triple -swift-version 6 -verify -verify-additional-prefix ni- %s -o /dev/null
|
|
// RUN: %target-swift-frontend -emit-sil -strict-concurrency=complete -target %target-swift-5.1-abi-triple -swift-version 6 -verify -verify-additional-prefix ni-ns- %s -o /dev/null -enable-upcoming-feature NonisolatedNonsendingByDefault
|
|
|
|
// REQUIRES: concurrency
|
|
// REQUIRES: asserts
|
|
// REQUIRES: swift_feature_NonisolatedNonsendingByDefault
|
|
|
|
// This test validates the behavior of transfernonsendable around initializers.
|
|
|
|
////////////////////////
|
|
// MARK: Declarations //
|
|
////////////////////////
|
|
|
|
class NonSendableKlass {}
|
|
@MainActor func transferToMain<T>(_ t: T) async {}
|
|
|
|
actor CustomActorInstance {}
|
|
|
|
@globalActor
|
|
struct CustomActor {
|
|
static let shared = CustomActorInstance()
|
|
}
|
|
|
|
/////////////////
|
|
// MARK: Tests //
|
|
/////////////////
|
|
|
|
actor ActorWithSynchronousNonIsolatedInit {
|
|
let k: NonSendableKlass
|
|
|
|
init(_ newK: NonSendableKlass) {
|
|
k = NonSendableKlass()
|
|
|
|
helper(newK)
|
|
|
|
// TODO: This should say actor isolated.
|
|
let _ = { @MainActor in
|
|
print(newK) // expected-error {{sending 'newK' risks causing data races}}
|
|
// expected-ni-note @-1 {{'self'-isolated 'newK' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
|
|
// expected-ni-ns-note @-2 {{'self'-isolated 'newK' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
|
|
}
|
|
}
|
|
|
|
init(x newK: NonSendableKlass) {
|
|
k = newK
|
|
|
|
helper(newK)
|
|
|
|
let _ = { @MainActor in
|
|
print(newK) // expected-error {{sending 'newK' risks causing data races}}
|
|
// expected-note @-1 {{'self'-isolated 'newK' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
|
|
}
|
|
}
|
|
|
|
init(ns: NonSendableKlass) async {
|
|
self.k = NonSendableKlass()
|
|
self.isolatedHelper(ns)
|
|
}
|
|
|
|
nonisolated func helper(_ newK: NonSendableKlass) {}
|
|
func isolatedHelper(_ newK: NonSendableKlass) {}
|
|
}
|
|
|
|
func initActorWithSyncNonIsolatedInit() {
|
|
let k = NonSendableKlass()
|
|
// TODO: This should say actor isolated.
|
|
_ = ActorWithSynchronousNonIsolatedInit(k) // expected-error {{sending 'k' risks causing data races}}
|
|
// expected-note @-1 {{sending 'k' to actor-isolated initializer 'init(_:)' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
let _ = { @MainActor in // expected-note {{access can happen concurrently}}
|
|
print(k)
|
|
}
|
|
}
|
|
|
|
func initActorWithSyncNonIsolatedInit2(_ k: NonSendableKlass) {
|
|
// TODO: This should say actor isolated.
|
|
_ = ActorWithSynchronousNonIsolatedInit(k) // expected-error {{sending 'k' risks causing data races}}
|
|
// expected-note @-1 {{sending 'k' to actor-isolated initializer 'init(_:)' risks causing data races between actor-isolated code and code in the current isolation context}}
|
|
let _ = { @MainActor in
|
|
print(k) // expected-error {{sending 'k' risks causing data races}}
|
|
// expected-note @-1 {{'k' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against code in the current isolation context}}
|
|
}
|
|
}
|
|
|
|
actor ActorWithAsyncIsolatedInit {
|
|
init(_ newK: NonSendableKlass) async {
|
|
let _ = { @MainActor in
|
|
print(newK) // expected-error {{sending 'newK' risks causing data races}}
|
|
// expected-note @-1 {{'self'-isolated 'newK' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later actor-isolated uses}}
|
|
}
|
|
}
|
|
}
|
|
|
|
func initActorWithAsyncIsolatedInit() async {
|
|
let k = NonSendableKlass()
|
|
// TODO: This should say actor isolated.
|
|
_ = await ActorWithAsyncIsolatedInit(k) // expected-error {{sending 'k' risks causing data races}}
|
|
// expected-note @-1 {{sending 'k' to actor-isolated initializer 'init(_:)' risks causing data races between actor-isolated and local nonisolated uses}}
|
|
let _ = { @MainActor in // expected-note {{access can happen concurrently}}
|
|
print(k)
|
|
}
|
|
}
|
|
|
|
func initActorWithAsyncIsolatedInit2(_ k: NonSendableKlass) async {
|
|
// TODO: This should say actor isolated.
|
|
_ = await ActorWithAsyncIsolatedInit(k) // expected-error {{sending 'k' risks causing data races}}
|
|
// expected-note @-1 {{sending 'k' to actor-isolated initializer 'init(_:)' risks causing data races between actor-isolated code and code in the current isolation context}}
|
|
let _ = { @MainActor in
|
|
print(k) // expected-error {{sending 'k' risks causing data races}}
|
|
// expected-note @-1 {{'k' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against code in the current isolation context}}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////
|
|
// MARK: Actor-Isolated Class //
|
|
////////////////////////////////
|
|
|
|
@CustomActor
|
|
class ClassWithSynchronousNonIsolatedInit {
|
|
nonisolated init(_ newK: NonSendableKlass) {
|
|
// We do not error on this since helper is nonisolated and newK is
|
|
// considered task isolated.
|
|
helper(newK)
|
|
|
|
let _ = { @MainActor in
|
|
print(newK) // expected-error {{sending 'newK' risks causing data races}}
|
|
// expected-note @-1 {{'newK' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against code in the current isolation context}}
|
|
}
|
|
}
|
|
|
|
nonisolated func helper(_ newK: NonSendableKlass) {}
|
|
}
|
|
|
|
func initClassWithSyncNonIsolatedInit() {
|
|
let k = NonSendableKlass()
|
|
_ = ClassWithSynchronousNonIsolatedInit(k)
|
|
let _ = { @MainActor in
|
|
print(k)
|
|
}
|
|
}
|
|
|
|
func initClassWithSyncNonIsolatedInit2(_ k: NonSendableKlass) {
|
|
_ = ClassWithSynchronousNonIsolatedInit(k)
|
|
let _ = { @MainActor in
|
|
print(k) // expected-error {{sending 'k' risks causing data races}}
|
|
// expected-note @-1 {{'k' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against code in the current isolation context}}
|
|
}
|
|
}
|
|
|
|
@CustomActor
|
|
class ClassWithAsyncIsolatedInit {
|
|
init(_ newK: NonSendableKlass) async {
|
|
let _ = { @MainActor in
|
|
print(newK) // expected-error {{sending 'newK' risks causing data races}}
|
|
// expected-note @-1 {{global actor 'CustomActor'-isolated 'newK' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later global actor 'CustomActor'-isolated uses}}
|
|
}
|
|
}
|
|
}
|
|
|
|
func initClassWithAsyncIsolatedInit() async {
|
|
let k = NonSendableKlass()
|
|
// TODO: Might make sense to emit a more specific error here since the closure
|
|
// is MainActor isolated. The actual capture is initially not isolated to
|
|
// MainActor.
|
|
_ = await ClassWithAsyncIsolatedInit(k) // expected-error {{sending 'k' risks causing data races}}
|
|
// expected-note @-1 {{sending 'k' to global actor 'CustomActor'-isolated initializer 'init(_:)' risks causing data races between global actor 'CustomActor'-isolated and local nonisolated uses}}
|
|
let _ = { @MainActor in // expected-note {{access can happen concurrently}}
|
|
print(k)
|
|
}
|
|
}
|
|
|
|
func initClassWithAsyncIsolatedInit2(_ k: NonSendableKlass) async {
|
|
_ = await ClassWithAsyncIsolatedInit(k) // expected-error {{sending 'k' risks causing data races}}
|
|
// expected-note @-1 {{sending 'k' to global actor 'CustomActor'-isolated initializer 'init(_:)' risks causing data races between global actor 'CustomActor'-isolated code and code in the current isolation context}}
|
|
let _ = { @MainActor in
|
|
print(k) // expected-error {{sending 'k' risks causing data races}}
|
|
// expected-note @-1 {{'k' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against code in the current isolation context}}
|
|
}
|
|
}
|
|
|
|
// Iterating over an existential sequence parameter must not produce false
|
|
// positive RBI errors in any of these isolation contexts.
|
|
|
|
actor ActorWithExistentialSequenceInit {
|
|
init(sequence: any Sequence<Int>) {
|
|
for element in sequence {
|
|
_ = element
|
|
}
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
class MainActorClassWithExistentialSequenceInit {
|
|
init(sequence: any Sequence<Int>) {
|
|
for element in sequence {
|
|
_ = element
|
|
}
|
|
}
|
|
}
|
|
|
|
@CustomActor
|
|
class CustomActorClassWithExistentialSequenceInit {
|
|
init(sequence: any Sequence<Int>) async {
|
|
for element in sequence {
|
|
_ = element
|
|
}
|
|
}
|
|
}
|
|
|
|
func nonisolatedFuncWithExistentialSequence(sequence: any Sequence<Int>) {
|
|
for element in sequence {
|
|
_ = element
|
|
}
|
|
}
|
|
|
|
// Class-constrained variant: the iterator associated type is AnyObject-constrained,
|
|
// so erasing it into an existential uses init_existential_ref (not init_existential_addr).
|
|
// This exercises the visitInitExistentialRefInst fix path.
|
|
|
|
protocol FakeClassIterator: AnyObject {
|
|
func nextElement()
|
|
}
|
|
|
|
protocol FakeClassSequence {
|
|
associatedtype Iterator: FakeClassIterator
|
|
func makeIterator() -> Iterator
|
|
}
|
|
|
|
actor ActorWithClassExistentialSequenceInit {
|
|
init(sequence: any FakeClassSequence) {
|
|
let iter: any FakeClassIterator = sequence.makeIterator()
|
|
iter.nextElement()
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
class MainActorClassWithClassExistentialSequenceInit {
|
|
init(sequence: any FakeClassSequence) {
|
|
let iter: any FakeClassIterator = sequence.makeIterator()
|
|
iter.nextElement()
|
|
}
|
|
}
|
|
|
|
func nonisolatedFuncWithClassExistentialSequence(sequence: any FakeClassSequence) {
|
|
let iter: any FakeClassIterator = sequence.makeIterator()
|
|
iter.nextElement()
|
|
}
|