Files
swift-mirror/test/Interpreter/consume_operator_kills_copyable_values.swift.gyb
Nate Chandler 40bcc74b47 [OSSACanOwned] Don't dead-end extend if consumed.
When the utility is used by the ConsumeOperatorCopyableValuesChecker,
the checker guarantees that the lifetime can end at the consumes, that
there are no uses after those consumes.  In that circumstance, the
utility maintains liveness to those consumes and as far as possible
without introducing a copy everywhere else.

The lack of complete lifetimes has forced the utility to extend liveness
of values to dead-ends.  That extension, however, is in tension with the
use that the checker is putting the utility to.  If there is a dead-end
after a consume, liveness must not be maintained to that dead-end.

rdar://147586673
2025-04-21 18:09:30 -07:00

212 lines
5.7 KiB
Swift

// RUN: %target-run-simple-swiftgyb(-Xfrontend -sil-verify-all) | %FileCheck %t/main.swift
// RUN: %target-run-simple-swiftgyb(-O -Xfrontend -sil-verify-all) | %FileCheck %t/main.swift
// This test uses gyb substitute let and var in as the introducers for the
// vardecls that are consumed. This guarantees that the same ordering results
// from checking the consume operator when applied to lets as when applied to
// lets.
// REQUIRES: executable_test
class X {
let number: Int
let function: StaticString
let line: UInt
init(_ number: Int, function: StaticString = #function, line: UInt = #line) {
self.number = number
self.function = function
self.line = line
print("hi - \(function) - \(number) - \(line)")
}
deinit {
print("adios - \(function) - \(number) - \(line)")
}
}
func barrier(_ name: String = "", function: StaticString = #function, line: UInt = #line) {
print("barrier - \(name) - \(function) - \(line)")
}
func endcap(name: String, _ args: [Any], function: StaticString = #function, line: UInt = #line) {
print("\(name) \(function)(", terminator: "")
for (index, arg) in args.enumerated() {
print(arg, terminator: "")
if index != args.count - 1 {
print(", ", terminator: "")
}
}
print(") - \(line)")
}
func begin(_ args: [Any], function: StaticString = #function, line: UInt = #line) {
endcap(name: "begin", args, function: function, line: line)
}
func end(_ args: [Any], function: StaticString = #function, line: UInt = #line) {
endcap(name: "end", args, function: function, line: line)
}
func takeX(_ x: consuming X) {}
% for introducer in ["let", "var"]:
func simple_${introducer}() {
// CHECK-LABEL: begin simple_{{let|var}}
begin([])
do {
// CHECK: hi
${introducer} x = X(0)
// CHECK: adios
takeX(consume x)
// CHECK: barrier
barrier()
}
// CHECK-LABEL: end simple_{{let|var}}
end([])
}
// CHECK-LABEL: begin testLeft_{{let|var}}(_:)(true)
// CHECK: hi
// CHECK: adios
// CHECK: barrier - left
// CHECK: barrier - end
// CHECK-LABEL: end testLeft_{{let|var}}(_:)(true)
// CHECK-LABEL: begin testLeft_{{let|var}}(_:)(false)
// CHECK: hi
// CHECK: barrier - right
// CHECK: adios
// CHECK: barrier - end
// CHECK-LABEL: end testLeft_{{let|var}}(_:)(false)
func testLeft_${introducer}(_ condition: Bool) {
begin([condition])
do {
${introducer} x = X(0)
if condition {
takeX(consume x)
barrier("left")
} else {
barrier("right")
}
barrier("end")
}
end([condition])
}
// CHECK-LABEL: begin testNested1_{{let|var}}(_:_:)(false, false)
// CHECK: hi
// CHECK: barrier - not c1, not c2
// CHECK: barrier - not c1
// CHECK: adios
// CHECK-LABEL: end testNested1_{{let|var}}(_:_:)(false, false)
// CHECK-LABEL: begin testNested1_{{let|var}}(_:_:)(false, true)
// CHECK: hi
// CHECK: barrier - not c1, c2
// CHECK: barrier - not c1
// CHECK: adios
// CHECK-LABEL: end testNested1_{{let|var}}(_:_:)(false, true)
// CHECK-LABEL: begin testNested1_{{let|var}}(_:_:)(true, false)
// CHECK: hi
// CHECK: adios
// CHECK: barrier - c2
// CHECK-LABEL: end testNested1_{{let|var}}(_:_:)(true, false)
// CHECK-LABEL: begin testNested1_{{let|var}}(_:_:)(true, true)
// CHECK: hi
// CHECK: adios
// CHECK: barrier - c2
// CHECK-LABEL: end testNested1_{{let|var}}(_:_:)(true, true)
func testNested1_${introducer}(_ c1: Bool, _ c2: Bool) {
begin([c1, c2])
do {
${introducer} x = X(0)
if c1 {
takeX(consume x)
barrier("c2")
} else {
if c2 {
takeX(x)
barrier("not c1, c2")
} else {
barrier("not c1, not c2")
}
barrier("not c1")
}
}
end([c1, c2])
}
// CHECK-LABEL: begin testNested2_{{let|var}}(_:_:)(false, false)
// CHECK: hi
// CHECK: barrier - not c1, not c2
// CHECK: adios
// CHECK: barrier - not c1
// CHECK-LABEL: end testNested2_{{let|var}}(_:_:)(false, false)
// CHECK-LABEL: begin testNested2_{{let|var}}(_:_:)(false, true)
// CHECK: hi
// CHECK: adios
// CHECK: barrier - not c1, c2
// CHECK: barrier - not c1
// CHECK-LABEL: end testNested2_{{let|var}}(_:_:)(false, true)
// CHECK-LABEL: begin testNested2_{{let|var}}(_:_:)(true, false)
// CHECK: hi
// CHECK: adios
// CHECK: barrier - c1
// CHECK-LABEL: end testNested2_{{let|var}}(_:_:)(true, false)
// CHECK-LABEL: begin testNested2_{{let|var}}(_:_:)(true, true)
// CHECK: hi
// CHECK: adios
// CHECK: barrier - c1
// CHECK-LABEL: end testNested2_{{let|var}}(_:_:)(true, true)
func testNested2_${introducer}(_ c1: Bool, _ c2: Bool) {
begin([c1, c2])
do {
${introducer} x = X(0)
if c1 {
takeX(consume x)
barrier("c1")
} else {
if c2 {
takeX(consume x)
barrier("not c1, c2")
} else {
barrier("not c1, not c2")
}
barrier("not c1")
}
}
end([c1, c2])
}
// CHECK-LABEL: begin testDeadEnd_{{let|var}}(_:)(true)
// CHECK: hi
// CHECK: adios
// CHECK: barrier
// CHECK-LABEL: end testDeadEnd_{{let|var}}(_:)(true)
func testDeadEnd_${introducer}(_ condition: Bool) {
begin([condition])
${introducer} x = X(0)
_ = consume x
guard condition else { fatalError() }
barrier()
end([condition])
}
func main_${introducer}() {
simple_${introducer}()
testLeft_${introducer}(true)
testLeft_${introducer}(false)
testNested1_${introducer}(false, false)
testNested1_${introducer}(false, true)
testNested1_${introducer}(true, false)
testNested1_${introducer}(true, true)
testNested2_${introducer}(false, false)
testNested2_${introducer}(false, true)
testNested2_${introducer}(true, false)
testNested2_${introducer}(true, true)
testDeadEnd_${introducer}(true)
}
% end
main_let()
main_var()