mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
When projecting an existential into an opened archetype, bind the archetype with metadata and witness tables extracted from the existential. Tweak SILGen so that it doesn't destroy the opened archetype value an extra two times. Use an executable testcase to ensure end-to-end operation, because we still don't have a parsable form existential projection to opened archetype instructions. Swift SVN r13755
98 lines
1.9 KiB
Swift
98 lines
1.9 KiB
Swift
// RUN: %target-run-simple-swift | FileCheck %s
|
|
|
|
// Test IR generation via execution for DynamicSelf.
|
|
|
|
protocol P {
|
|
func f() -> DynamicSelf
|
|
func g() -> DynamicSelf
|
|
}
|
|
|
|
@class_protocol protocol CP {
|
|
func f() -> DynamicSelf
|
|
func g() -> DynamicSelf
|
|
}
|
|
|
|
func callDynamicSelfExistential(p: P) {
|
|
println("Before first call")
|
|
var p2 = p.f()
|
|
println("Between calls")
|
|
p2.g()
|
|
println("After second call")
|
|
}
|
|
|
|
func callDynamicSelfClassExistential(cp: CP) {
|
|
println("Before first call")
|
|
var cp2 = cp.f()
|
|
println("Between calls")
|
|
cp2.g()
|
|
println("After second call")
|
|
}
|
|
|
|
struct S : P {
|
|
func f() -> S {
|
|
println("S.f()")
|
|
return self
|
|
}
|
|
|
|
func g() -> S {
|
|
println("S.g()")
|
|
return self
|
|
}
|
|
}
|
|
|
|
class C : P, CP {
|
|
init() {
|
|
println("Allocating C")
|
|
}
|
|
|
|
destructor() {
|
|
println("Destroying C")
|
|
}
|
|
|
|
func f() -> DynamicSelf {
|
|
println("C.f()")
|
|
return self
|
|
}
|
|
|
|
func g() -> DynamicSelf {
|
|
println("C.g()")
|
|
return self
|
|
}
|
|
}
|
|
|
|
println("-------------------------------")
|
|
|
|
// CHECK: S() as non-class existential
|
|
println("S() as non-class existential")
|
|
// CHECK-NEXT: Before first call
|
|
// CHECK-NEXT: S.f()
|
|
// CHECK-NEXT: Between calls
|
|
// CHECK-NEXT: S.g()
|
|
// CHECK-NEXT: After second call
|
|
callDynamicSelfExistential(S())
|
|
|
|
// CHECK-NEXT: C() as non-class existential
|
|
println("C() as non-class existential")
|
|
// CHECK-NEXT: Allocating C
|
|
// CHECK-NEXT: Before first call
|
|
// CHECK-NEXT: C.f()
|
|
// CHECK-NEXT: Between calls
|
|
// CHECK-NEXT: C.g()
|
|
// CHECK-NEXT: After second call
|
|
// CHECK-NEXT: Destroying C
|
|
callDynamicSelfExistential(C())
|
|
|
|
// CHECK-NEXT: C() as class existential
|
|
println("C() as class existential")
|
|
// CHECK-NEXT: Allocating C
|
|
// CHECK-NEXT: Before first call
|
|
// CHECK-NEXT: C.f()
|
|
// CHECK-NEXT: Between calls
|
|
// CHECK-NEXT: C.g()
|
|
// CHECK-NEXT: After second call
|
|
// CHECK-NEXT: Destroying C
|
|
callDynamicSelfClassExistential(C())
|
|
|
|
// CHECK-NEXT: Done
|
|
println("Done")
|