mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
309 lines
11 KiB
Swift
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)
|