Files
swift-mirror/test/Concurrency/concurrentfunction_capturediagnostics.swift
Daniel Rodríguez Troitiño ba68faaed5 [test] Mark tests that use experimental/upcoming features as such
Find all the usages of `--enable-experimental-feature` or
`--enable-upcoming-feature` in the tests and replace some of the
`REQUIRES: asserts` to use `REQUIRES: swift-feature-Foo` instead, which
should correctly apply to depending on the asserts/noasserts mode of the
toolchain for each feature.

Remove some comments that talked about enabling asserts since they don't
apply anymore (but I might had miss some).

All this was done with an automated script, so some formatting weirdness
might happen, but I hope I fixed most of those.

There might be some tests that were `REQUIRES: asserts` that might run
in `noasserts` toolchains now. This will normally be because their
feature went from experimental to upcoming/base and the tests were not
updated.
2024-11-02 11:46:46 -07:00

222 lines
7.3 KiB
Swift

// RUN: %target-swift-frontend -print-diagnostic-groups -target %target-swift-5.1-abi-triple -enable-experimental-flow-sensitive-concurrent-captures -verify -emit-sil %s -o - >/dev/null
// RUN: %target-swift-frontend -print-diagnostic-groups -target %target-swift-5.1-abi-triple -enable-experimental-flow-sensitive-concurrent-captures -verify -emit-sil %s -o - >/dev/null -strict-concurrency=targeted
// RUN: %target-swift-frontend -print-diagnostic-groups -target %target-swift-5.1-abi-triple -enable-experimental-flow-sensitive-concurrent-captures -verify -emit-sil %s -o - >/dev/null -strict-concurrency=complete
// RUN: %target-swift-frontend -print-diagnostic-groups -target %target-swift-5.1-abi-triple -enable-experimental-flow-sensitive-concurrent-captures -verify -emit-sil %s -o - >/dev/null -strict-concurrency=complete -enable-upcoming-feature RegionBasedIsolation
// REQUIRES: concurrency
// REQUIRES: swift_feature_RegionBasedIsolation
func f(_: @escaping @Sendable () -> Void) { }
open class F {
func useConcurrent(_: @escaping @Sendable () -> Void) { }
}
extension Int {
mutating func addOne() {
self += 1
}
}
func inoutUserInt(_ t: inout Int) {}
func testCaseTrivialValue() {
var i = 17
f {
print(i + 17)
print(i + 18)
print(i + 19)
}
i = 20
i += 21
// We only emit a warning here since we use the last write.
//
// TODO: Should we emit for all writes?
i.addOne() // expected-warning {{'i' mutated after capture by sendable closure}}
// expected-note @-14 {{variable defined here}}
// expected-note @-14 {{variable captured by sendable closure}}
// expected-note @-14 {{capturing use}}
// expected-note @-14 {{capturing use}}
// expected-note @-14 {{capturing use}}
}
func testCaseTrivialValue2() {
var i2 = 17
f {
print(i2 + 17)
print(i2 + 18)
print(i2 + 19)
}
i2 = 20
i2 += 21 // expected-warning {{'i2' mutated after capture by sendable closure}}
// expected-note @-9 {{variable defined here}}
// expected-note @-9 {{variable captured by sendable closure}}
// expected-note @-9 {{capturing use}}
// expected-note @-9 {{capturing use}}
// expected-note @-9 {{capturing use}}
}
func testCaseTrivialValue3() {
var i3 = 17
f {
print(i3 + 17)
print(i3 + 18)
print(i3 + 19)
}
i3 = 20 // expected-warning {{'i3' mutated after capture by sendable closure}}
// expected-note @-8 {{variable defined here}}
// expected-note @-8 {{variable captured by sendable closure}}
// expected-note @-8 {{capturing use}}
// expected-note @-8 {{capturing use}}
// expected-note @-8 {{capturing use}}
}
func testCaseTrivialValue4() {
var i4 = 17
f {
print(i4 + 17)
print(i4 + 18)
print(i4 + 19)
}
inoutUserInt(&i4) // expected-warning {{'i4' mutated after capture by sendable closure}}
// expected-note @-8 {{variable defined here}}
// expected-note @-8 {{variable captured by sendable closure}}
// expected-note @-8 {{capturing use}}
// expected-note @-8 {{capturing use}}
// expected-note @-8 {{capturing use}}
}
class Klass: UnsafeSendable { // expected-warning{{'UnsafeSendable' is deprecated: Use @unchecked Sendable instead [DeprecatedDeclaration]}}
var next: Klass? = nil
}
func inoutUserKlass(_ k: inout Klass) {}
func inoutUserOptKlass(_ k: inout Klass?) {}
func testCaseClass() {
var i = Klass()
f {
print(i)
}
i = Klass() // expected-warning {{'i' mutated after capture by sendable closure}}
// expected-note @-6 {{variable defined here}}
// expected-note @-6 {{variable captured by sendable closure}}
// expected-note @-6 {{capturing use}}
}
func testCaseClassInout() {
var i2 = Klass()
f {
print(i2)
}
inoutUserKlass(&i2) // expected-warning {{'i2' mutated after capture by sendable closure}}
// expected-note @-5 {{variable defined here}}
// expected-note @-5 {{variable captured by sendable closure}}
// expected-note @-5 {{capturing use}}
}
func testCaseClassInoutField() {
var i2 = Klass()
i2 = Klass()
f {
print(i2)
}
// Since we are passing in .next inout and we are using a class this isn't a
// violation.
inoutUserOptKlass(&i2.next)
}
////////////////////////////
// Non Trivial Value Type //
////////////////////////////
struct NonTrivialValueType: Sendable {
var i: Int
var k: Klass? = nil
init(_ inputI: Int, _ inputKlass: Klass) {
self.i = inputI
self.k = inputKlass
}
}
func testCaseNonTrivialValue() {
var i = NonTrivialValueType(17, Klass())
f {
print(i.i + 17)
print(i.i + 18)
print(i.i + 19)
}
i.i = 20
i.i += 21
// We only emit a warning here since we use the last write.
//
// TODO: Should we emit for all writes?
i.i.addOne() // expected-warning {{'i' mutated after capture by sendable closure}}
// expected-note @-14 {{variable defined here}}
// expected-note @-14 {{variable captured by sendable closure}}
// expected-note @-14 {{capturing use}}
// expected-note @-14 {{capturing use}}
// expected-note @-14 {{capturing use}}
}
func testCaseNonTrivialValueInout() {
var i = NonTrivialValueType(17, Klass())
f {
print(i.i + 17)
print(i.k ?? "none")
}
// We only emit a warning here since we use the last write.
inoutUserOptKlass(&i.k) // expected-warning {{'i' mutated after capture by sendable closure}}
// expected-note @-8 {{variable defined here}}
// expected-note @-8 {{variable captured by sendable closure}}
// expected-note @-8 {{capturing use}}
// expected-note @-8 {{capturing use}}
}
protocol MyProt {
var i: Int { get set }
var k: Klass? { get set }
}
func testCaseAddressOnlyAllocBoxToStackable<T : MyProt & Sendable>(i : T) {
var i2 = i
f {
print(i2.i + 17)
print(i2.k ?? "none")
}
// TODO: Make sure we emit these once we support address only types!
inoutUserOptKlass(&i2.k) // xpected-warning {{'i2' mutated after capture by sendable closure}}
// xpected-note @-8 {{variable defined here}}
// xpected-note @-8 {{variable captured by sendable closure}}
// xpected-note @-8 {{capturing use}}
// xpected-note @-8 {{capturing use}}
}
// Alloc box to stack can't handle this test case, so show off a bit and make
// sure we can emit a great diagnostic here!
func testCaseAddressOnlyNoAllocBoxToStackable<T : MyProt & Sendable>(i : T) {
let f2 = F()
var i2 = i
f2.useConcurrent {
print(i2.i + 17)
print(i2.k ?? "none")
}
// TODO: Make sure we emit these once we support address only types!
inoutUserOptKlass(&i2.k) // xpected-warning {{'i2' mutated after capture by sendable closure}}
// xpected-note @-8 {{variable defined here}}
// xpected-note @-8 {{variable captured by sendable closure}}
// xpected-note @-8 {{capturing use}}
// xpected-note @-8 {{capturing use}}
}