Files
swift-mirror/test/Interpreter/moveonly_discard.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

210 lines
4.6 KiB
Swift

// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-feature -Xfrontend MoveOnlyEnumDeinits -Xfrontend -sil-verify-all) | %FileCheck %s --implicit-check-not closing
// RUN: %target-run-simple-swift(-O -Xfrontend -enable-experimental-feature -Xfrontend MoveOnlyEnumDeinits -Xfrontend -sil-verify-all) | %FileCheck %s --implicit-check-not closing
// REQUIRES: executable_test
// REQUIRES: swift_feature_MoveOnlyEnumDeinits
// NOTE: it's important that this test has the `--implicit-check-not closing` flag to catch double deinits!!
// you also want to make sure all messages start with "closing"
func posix_close(_ x: Int) { print("closing file descriptor: \(x)") }
func print_closing_MFD() { print("closing MaybeFileDescriptor") }
enum E: Error { case err }
struct FileDescriptor: ~Copyable {
var fd: Int
static var nextFD: Int = 0
consuming func discard() { discard self }
init() {
self.fd = FileDescriptor.nextFD
FileDescriptor.nextFD += 1
}
init(doDiscard: Bool) throws {
self.init()
if doDiscard {
discard()
throw E.err
}
}
__consuming func close() {
posix_close(fd)
discard self
}
__consuming func justDiscard() {
discard self
}
__consuming func empty() {}
var takeFileDescriptorWrong : Int {
__consuming get {
return fd
}
}
var takeFileDescriptorRight : Int {
__consuming get {
let x = fd
discard self
return x
}
}
deinit {
posix_close(fd)
}
}
enum MaybeFileDescriptor: ~Copyable {
case some(FileDescriptor)
case nothing
consuming func discard() { discard self }
init(reinit: Bool) {
self = .some(FileDescriptor())
if reinit {
discard()
self = .some(FileDescriptor())
}
}
__consuming func skipDeinit() {
discard self
}
deinit {
// we can't do a borrowed switch yet so this is just printing some message
print_closing_MFD()
}
}
struct SillyEmptyGeneric<T>: ~Copyable {
consuming func identity(_ t: T) -> T {
discard self
return t
}
deinit { fatalError("ran unexpectedly!") }
}
struct SingleMutableField: ~Copyable {
var value = 0
consuming func justDiscard() {
discard self
}
deinit {
print("SingleMutableField.deinit")
}
}
// rdar://110232973 ([move-only] Checker should distinguish in between
// field of single field struct vs parent field itself (was: mutation
// of field in noncopyable struct should not trigger deinit))
//
// This test must not be in a closure.
@inline(never)
func testSingleMutableFieldNoMemberReinit() {
var x = SingleMutableField()
x.value = 20 // should not trigger deinit.
// CHECK-NOT: SingleMutableField.deinit
x.justDiscard()
}
func main() {
testSingleMutableFieldNoMemberReinit()
let _ = {
let x = FileDescriptor() // 0
x.close()
// CHECK: closing file descriptor: 0
}()
let _ = {
let _ = FileDescriptor() // 1
// CHECK: closing file descriptor: 1
}()
let _ = {
let x = FileDescriptor() // 2
x.justDiscard()
}()
let _ = {
let x = FileDescriptor() // 3
x.empty()
// CHECK: closing file descriptor: 3
}()
let _ = {
let x = FileDescriptor() // 4
_ = x.takeFileDescriptorWrong
// CHECK: closing file descriptor: 4
}()
let _ = {
let x = FileDescriptor() // 5
_ = x.takeFileDescriptorRight
}()
let _ = {
do {
// should throw before getting to close()
let x = try FileDescriptor(doDiscard: true) // 6
x.close()
} catch {}
}()
let _ = {
do {
let x = try FileDescriptor(doDiscard: false) // 7
x.close()
} catch {}
// CHECK: closing file descriptor: 7
}()
let _ = {
let _ = MaybeFileDescriptor(reinit: true) // 8 & 9
// CHECK: closing file descriptor: 8
// CHECK: closing MaybeFileDescriptor
// CHECK: closing file descriptor: 9
}()
let _ = {
let x = MaybeFileDescriptor(reinit: true) // 10 & 11
x.skipDeinit() // this skips the enum's deinit, not the file descriptor's!
// CHECK: closing file descriptor: 10
// CHECK: closing file descriptor: 11
}()
let _ = {
var maybe = MaybeFileDescriptor.nothing
maybe = .some(FileDescriptor()) // 12
// CHECK: closing MaybeFileDescriptor
// CHECK: closing MaybeFileDescriptor
// CHECK: closing file descriptor: 12
}()
let _ = {
let x = MaybeFileDescriptor(reinit: false) // 13
x.skipDeinit() // this skips the enum's deinit, not the file descriptor's!
// CHECK: closing file descriptor: 13
}()
let _ = {
let x = SillyEmptyGeneric<[Int]>()
let z = [1, 2]
let ans = x.identity(z)
assert(z == ans)
}()
}
main()