Files
swift-mirror/test/Interpreter/moveonly_address_maximize.swift
Kavon Farvardin 0420310623 NCGenerics: it's no longer "experimental"
resolves rdar://127701059
2024-05-08 10:49:12 -07:00

309 lines
11 KiB
Swift

// RUN: %target-run-simple-swift(-Xfrontend -sil-verify-all) | %FileCheck %s
// RUN: %target-run-simple-swift(-O -Xfrontend -sil-verify-all) | %FileCheck %s
// REQUIRES: executable_test
struct S : ~Copyable {
let s: String
init(_ s: String) { self.s = s }
deinit {
print("destroying \(s)")
}
}
struct S2 : ~Copyable {
var s1: S
var s2: S
init(_ s: String) {
self.s1 = S("\(s).s1")
self.s2 = S("\(s).s2")
}
}
struct S3 : ~Copyable {
var s1: S
var s2: S
var s3: S
init(_ s: String) {
self.s1 = S("\(s).s1")
self.s2 = S("\(s).s2")
self.s3 = S("\(s).s3")
}
}
func consumeVal(_ s: consuming S) {}
func consumeVal(_ s: consuming S2) {}
func borrowVal(_ s: borrowing S) {}
func borrowVal(_ s: borrowing S2) {}
func marker(_ s: String) {
print("\(#function): \(s)")
}
// Simple test that makes sure that we still after we consume have the lifetime
// of s be completely consumed by consumeVal.
// CHECK: destroying simpleTestVar().first.s1
// CHECK: destroying simpleTestVar().first.s2
// CHECK: destroying simpleTestVar().second.s1
// CHECK: destroying simpleTestVar().second.s2
// CHECK: marker(_:): simpleTestVar().1
@_silgen_name("simpleTestVar")
func simpleTestVar() {
var s = S2("\(#function).first")
s = S2("\(#function).second")
consumeVal(s) // Lifetime of s should end here before end of scope.
marker("\(#function).1")
}
// Simple test that proves that we can maximize lifetimes in a field sensitive
// manner. Since we only consume s.s1, s.s2's lifetime should still be maximized
// and be at end of scope.
// CHECK: destroying simpleTestVar2().first.s1
// CHECK: destroying simpleTestVar2().first.s2
// CHECK: destroying simpleTestVar2().second.s1
// CHECK: marker(_:): simpleTestVar2().1
// CHECK: destroying simpleTestVar2().second.s2
func simpleTestVar2() {
var s = S2("\(#function).first")
s = S2("\(#function).second")
consumeVal(s.s1) // Lifetime of s1 should end here.
marker("\(#function).1")
// Lifetime of s2 should end at end of scope after marker.
}
// In this case, we consume all of s by consuming s.s1 and s.s2 separately, so
// all lifetimes should be done before marker.
// CHECK: destroying simpleTestVar3().first.s1
// CHECK: destroying simpleTestVar3().first.s2
// CHECK: destroying simpleTestVar3().second.s1
// CHECK: destroying simpleTestVar3().second.s2
// CHECK: marker(_:): simpleTestVar3().1
func simpleTestVar3() {
var s = S2("\(#function).first")
s = S2("\(#function).second")
consumeVal(s.s1)
consumeVal(s.s2)
marker("\(#function).1") // Lifetimes should end before marker.
}
// In this case, we completely consume s and then reinitialize s implying we
// need to deal with two disjoint lifetimes. The second lifetime of s should end
// after marker.
// CHECK: destroying simpleTestVar3a().first.s1
// CHECK: destroying simpleTestVar3a().first.s2
// CHECK: destroying simpleTestVar3a().second.s1
// CHECK: destroying simpleTestVar3a().second.s2
// CHECK: marker(_:): simpleTestVar3a().1
// CHECK: marker(_:): simpleTestVar3a().2
// CHECK: destroying simpleTestVar3a().third.s1
// CHECK: destroying simpleTestVar3a().third.s2
func simpleTestVar3a() {
var s = S2("\(#function).first")
s = S2("\(#function).second")
consumeVal(s.s1)
consumeVal(s.s2)
marker("\(#function).1")
s = S2("\(#function).third")
marker("\(#function).2")
}
// In this case, we have another borrowVal of s.s2. That should still let s.s2's
// lifetime end after marker.
// CHECK: destroying simpleTestVar3b().first.s1
// CHECK: destroying simpleTestVar3b().first.s2
// CHECK: destroying simpleTestVar3b().second.s1
// CHECK: marker(_:): simpleTestVar3b().1
// CHECK: destroying simpleTestVar3b().second.s2
func simpleTestVar3b() {
var s = S2("\(#function).first")
s = S2("\(#function).second")
consumeVal(s.s1)
borrowVal(s.s2)
marker("\(#function).1") // s2 should end its lifetime after marker.
}
// In this case, we are testing reinitialization and making sure that we can
// handle two initializations properly. We also are testing conditional merge
// logic. Since in both cases below s is completely consumed in b, s's lifetime
// would end at marker.
// CHECK: destroying simpleTestVar4(_:_:)[false, false)].first.s1
// CHECK: destroying simpleTestVar4(_:_:)[false, false)].first.s2
// CHECK: marker(_:): simpleTestVar4(_:_:)[false, false)].1
// CHECK: destroying simpleTestVar4(_:_:)[false, false)].second.s1
// CHECK: destroying simpleTestVar4(_:_:)[false, false)].second.s2
// CHECK: destroying simpleTestVar4(_:_:)[false, false)].third.s1
// CHECK: destroying simpleTestVar4(_:_:)[false, false)].third.s2
// CHECK: marker(_:): simpleTestVar4(_:_:)[false, false)].2
// CHECK: destroying simpleTestVar4(_:_:)[false, true)].first.s1
// CHECK: destroying simpleTestVar4(_:_:)[false, true)].first.s2
// CHECK: marker(_:): simpleTestVar4(_:_:)[false, true)].1
// CHECK: destroying simpleTestVar4(_:_:)[false, true)].second.s1
// CHECK: destroying simpleTestVar4(_:_:)[false, true)].second.s2
// CHECK: destroying simpleTestVar4(_:_:)[false, true)].third.s1
// CHECK: destroying simpleTestVar4(_:_:)[false, true)].third.s2
// CHECK: destroying simpleTestVar4(_:_:)[true, false)].first.s1
// CHECK: destroying simpleTestVar4(_:_:)[true, false)].first.s2
// CHECK: destroying simpleTestVar4(_:_:)[true, false)].second.s1
// CHECK: destroying simpleTestVar4(_:_:)[true, false)].second.s2
// CHECK: destroying simpleTestVar4(_:_:)[true, false)].third.s1
// CHECK: destroying simpleTestVar4(_:_:)[true, false)].third.s2
// CHECK: marker(_:): simpleTestVar4(_:_:)[true, false)].2
// CHECK: destroying simpleTestVar4(_:_:)[true, true)].first.s1
// CHECK: destroying simpleTestVar4(_:_:)[true, true)].first.s2
// CHECK: destroying simpleTestVar4(_:_:)[true, true)].second.s1
// CHECK: destroying simpleTestVar4(_:_:)[true, true)].second.s2
// CHECK: destroying simpleTestVar4(_:_:)[true, true)].third.s1
// CHECK: destroying simpleTestVar4(_:_:)[true, true)].third.s2
func simpleTestVar4(_ b1: Bool, _ b2: Bool) {
var s = S2("\(#function)[\(b1), \(b2))].first")
s = S2("\(#function)[\(b1), \(b2))].second")
if b1 {
consumeVal(s)
} else {
marker("\(#function)[\(b1), \(b2))].1")
// S's lifetime should end after marker in this block.
}
s = S2("\(#function)[\(b1), \(b2))].third")
if b2 {
consumeVal(s)
} else {
marker("\(#function)[\(b1), \(b2))].2")
// S's 2nd lifetime should end after marker in this block.
}
}
// This test is similar to the previous, except we are consuming different
// values along the if/else branch that completely covers the value. As a result
// of this, we need to end the lifetime of s in the branches.
// CHECK: destroying simpleTestVar6(_:)[false].first.s1
// CHECK: destroying simpleTestVar6(_:)[false].first.s2
// CHECK: destroying simpleTestVar6(_:)[false].second.s2
// CHECK: marker(_:): simpleTestVar6(_:)[false].2
// CHECK: destroying simpleTestVar6(_:)[false].second.s1
// CHECK: destroying simpleTestVar6(_:)[false].third.s1
// CHECK: destroying simpleTestVar6(_:)[false].third.s2
// CHECK: destroying simpleTestVar6(_:)[true].first.s1
// CHECK: destroying simpleTestVar6(_:)[true].first.s2
// CHECK: destroying simpleTestVar6(_:)[true].second.s1
// CHECK: marker(_:): simpleTestVar6(_:)[true].1
// CHECK: destroying simpleTestVar6(_:)[true].second.s2
// CHECK: destroying simpleTestVar6(_:)[true].third.s1
// CHECK: destroying simpleTestVar6(_:)[true].third.s2
func simpleTestVar6(_ b: Bool) {
var s = S2("\(#function)[\(b)].first")
s = S2("\(#function)[\(b)].second")
if b {
consumeVal(s.s1) // end of s.s1's lifetime.
marker("\(#function)[\(b)].1")
// s.s2 should end here.
} else {
consumeVal(s.s2) // end of s.s2's lifetime
marker("\(#function)[\(b)].2")
// end of s.s1's lifetime should end after marker.
}
s = S2("\(#function)[\(b)].third")
}
// In this case, we are using S3 implying we have three fields. So despite the
// fact that we are deleting these two values in the if-else branches, s3's
// lifetime needs to end at end of scope.
// CHECK: destroying simpleTestVar6a(_:)[false].first.s1
// CHECK: destroying simpleTestVar6a(_:)[false].first.s2
// CHECK: destroying simpleTestVar6a(_:)[false].first.s3
// CHECK: destroying simpleTestVar6a(_:)[false].second.s2
// CHECK: marker(_:): simpleTestVar6a(_:)[false].2
// CHECK: destroying simpleTestVar6a(_:)[false].second.s1
// CHECK: marker(_:): simpleTestVar6a(_:)[false].3
// CHECK: destroying simpleTestVar6a(_:)[false].second.s3
// CHECK: destroying simpleTestVar6a(_:)[true].first.s1
// CHECK: destroying simpleTestVar6a(_:)[true].first.s2
// CHECK: destroying simpleTestVar6a(_:)[true].first.s3
// CHECK: destroying simpleTestVar6a(_:)[true].second.s1
// CHECK: marker(_:): simpleTestVar6a(_:)[true].1
// CHECK: destroying simpleTestVar6a(_:)[true].second.s2
// CHECK: marker(_:): simpleTestVar6a(_:)[true].3
// CHECK: destroying simpleTestVar6a(_:)[true].second.s3
func simpleTestVar6a(_ b: Bool) {
var s = S3("\(#function)[\(b)].first")
s = S3("\(#function)[\(b)].second")
if b {
consumeVal(s.s1) // end of s.s1's lifetime.
marker("\(#function)[\(b)].1")
// s.s2 should end here.
} else {
consumeVal(s.s2) // end of s.s2's lifetime
marker("\(#function)[\(b)].2")
// end of s.s1's lifetime should end after marker.
}
marker("\(#function)[\(b)].3")
// s.s3's lifetime should end here.
}
// In this case, we are using S3, but we are consuming two disjoint parts of S
// in the if statement so we cover again completely.
// CHECK: destroying simpleTestVar6b(_:)[false].first.s1
// CHECK: destroying simpleTestVar6b(_:)[false].first.s2
// CHECK: destroying simpleTestVar6b(_:)[false].first.s3
// CHECK: destroying simpleTestVar6b(_:)[false].second.s2
// CHECK: marker(_:): simpleTestVar6b(_:)[false].2
// CHECK: destroying simpleTestVar6b(_:)[false].second.s3
// CHECK: destroying simpleTestVar6b(_:)[false].second.s1
// CHECK: marker(_:): simpleTestVar6b(_:)[false].3
// CHECK: destroying simpleTestVar6b(_:)[true].first.s1
// CHECK: destroying simpleTestVar6b(_:)[true].first.s2
// CHECK: destroying simpleTestVar6b(_:)[true].first.s3
// CHECK: destroying simpleTestVar6b(_:)[true].second.s1
// CHECK: destroying simpleTestVar6b(_:)[true].second.s3
// CHECK: marker(_:): simpleTestVar6b(_:)[true].1
// CHECK: destroying simpleTestVar6b(_:)[true].second.s2
// CHECK: marker(_:): simpleTestVar6b(_:)[true].3
func simpleTestVar6b(_ b: Bool) {
var s = S3("\(#function)[\(b)].first")
s = S3("\(#function)[\(b)].second")
if b {
consumeVal(s.s1) // end of s.s1's lifetime.
consumeVal(s.s3) // end of s.s3's lifetime
marker("\(#function)[\(b)].1")
// s.s2 should end here.
} else {
consumeVal(s.s2) // end of s.s2's lifetime
marker("\(#function)[\(b)].2")
// end of s.s1's lifetime should end after marker.
// end of s.s3's lifetime should end after marker.
}
marker("\(#function)[\(b)].3")
}
simpleTestVar()
simpleTestVar2()
simpleTestVar3()
simpleTestVar3a()
simpleTestVar3b()
simpleTestVar4(false, false)
simpleTestVar4(false, true)
simpleTestVar4(true, false)
simpleTestVar4(true, true)
simpleTestVar6(false)
simpleTestVar6(true)
simpleTestVar6a(false)
simpleTestVar6a(true)
simpleTestVar6b(false)
simpleTestVar6b(true)