Skip to content

Commit 9f58968

Browse files
committed
Add silgen and run-time tests
1 parent 33401ae commit 9f58968

File tree

2 files changed

+190
-41
lines changed

2 files changed

+190
-41
lines changed

test/Interpreter/dynamic_self.swift

Lines changed: 131 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,71 @@
66
protocol P {
77
func f() -> Self
88
func g() -> Self
9+
subscript() -> Self { get }
10+
var p: Self { get }
911
}
1012

1113
protocol CP : class {
1214
func f() -> Self
1315
func g() -> Self
16+
subscript() -> Self { get }
17+
var p: Self { get }
18+
}
19+
20+
extension P {
21+
func f() -> Self {
22+
print("[Self := \(Self.self), self is \(type(of: self))] P extension.f()")
23+
return self
24+
}
25+
func g() -> Self {
26+
print("[Self := \(Self.self), self is \(type(of: self))] P extension.g()")
27+
return self
28+
}
29+
subscript() -> Self {
30+
print("[Self := \(Self.self), self is \(type(of: self))] P extension.subscript()")
31+
return self
32+
}
33+
var p: Self {
34+
print("[Self := \(Self.self), self is \(type(of: self))] P extension.p")
35+
return self
36+
}
37+
}
38+
39+
extension CP {
40+
func f() -> Self {
41+
print("[Self := \(Self.self), self is \(type(of: self))] CP extension.f()")
42+
return self
43+
}
44+
func g() -> Self {
45+
print("[Self := \(Self.self), self is \(type(of: self))] CP extension.g()")
46+
return self
47+
}
48+
subscript() -> Self {
49+
print("[Self := \(Self.self), self is \(type(of: self))] CP extension.subscript()")
50+
return self
51+
}
52+
var p: Self {
53+
print("[Self := \(Self.self), self is \(type(of: self))] CP extension.p")
54+
return self
55+
}
1456
}
1557

1658
func callDynamicSelfExistential(_ p: P) {
17-
print("Before first call")
18-
var p2 = p.f()
19-
print("Between calls")
20-
p2.g()
21-
print("After second call")
59+
print("callDynamicSelfExistential {")
60+
let p2 = p.f()
61+
let p3 = p2.g()
62+
let p4 = p3[]
63+
let p5 = p4.p
64+
print(" } callDynamicSelfExistential")
2265
}
2366

2467
func callDynamicSelfClassExistential(_ cp: CP) {
25-
print("Before first call")
26-
var cp2 = cp.f()
27-
print("Between calls")
28-
cp2.g()
29-
print("After second call")
68+
print("callDynamicSelfClassExistential {")
69+
let cp2 = cp.f()
70+
let cp3 = cp2.g()
71+
let cp4 = cp3[]
72+
let cp5 = cp4.p
73+
print(" } callDynamicSelfClassExistential")
3074
}
3175

3276
struct S : P {
@@ -39,54 +83,101 @@ struct S : P {
3983
print("S.g()")
4084
return self
4185
}
42-
}
4386

44-
class C : P, CP {
45-
init() {
46-
print("Allocating C")
87+
subscript() -> S {
88+
print("S.subscript()")
89+
return self
90+
}
91+
92+
var p: S {
93+
print("S.p")
94+
return self
4795
}
96+
}
4897

98+
class C1a : P, CP {
4999
func f() -> Self {
50-
print("C.f()")
100+
print("C1a.f()")
51101
return self
52102
}
53103

54104
func g() -> Self {
55-
print("C.g()")
105+
print("C1a.g()")
106+
return self
107+
}
108+
109+
subscript() -> Self {
110+
print("C1a.subscript()")
111+
return self
112+
}
113+
114+
var p: Self {
115+
print("C1a.p")
56116
return self
57117
}
58118
}
119+
final class C1b : C1a {
120+
override subscript() -> Self {
121+
print("C1b.subscript()")
122+
return self
123+
}
124+
}
125+
126+
class C2a : P {}
127+
final class C2b : C2a {}
128+
129+
class C3a : CP {}
130+
final class C3b : C3a {}
59131

60132
print("-------------------------------")
61133

62-
// CHECK: S() as non-class existential
63-
print("S() as non-class existential")
64-
// CHECK-NEXT: Before first call
134+
// CHECK: callDynamicSelfExistential {
65135
// CHECK-NEXT: S.f()
66-
// CHECK-NEXT: Between calls
67136
// CHECK-NEXT: S.g()
68-
// CHECK-NEXT: After second call
137+
// CHECK-NEXT: S.subscript()
138+
// CHECK-NEXT: S.p
139+
// CHECK-NEXT: } callDynamicSelfExistential
69140
callDynamicSelfExistential(S())
70141

71-
// CHECK-NEXT: C() as non-class existential
72-
print("C() as non-class existential")
73-
// CHECK-NEXT: Allocating C
74-
// CHECK-NEXT: Before first call
75-
// CHECK-NEXT: C.f()
76-
// CHECK-NEXT: Between calls
77-
// CHECK-NEXT: C.g()
78-
// CHECK-NEXT: After second call
79-
callDynamicSelfExistential(C())
80-
81-
// CHECK-NEXT: C() as class existential
82-
print("C() as class existential")
83-
// CHECK-NEXT: Allocating C
84-
// CHECK-NEXT: Before first call
85-
// CHECK-NEXT: C.f()
86-
// CHECK-NEXT: Between calls
87-
// CHECK-NEXT: C.g()
88-
// CHECK-NEXT: After second call
89-
callDynamicSelfClassExistential(C())
142+
// CHECK-NEXT: callDynamicSelfExistential {
143+
// CHECK-NEXT: C1a.f()
144+
// CHECK-NEXT: C1a.g()
145+
// CHECK-NEXT: C1a.subscript()
146+
// CHECK-NEXT: C1a.p
147+
// CHECK-NEXT: } callDynamicSelfExistential
148+
callDynamicSelfExistential(C1a())
149+
150+
// CHECK-NEXT: callDynamicSelfExistential {
151+
// CHECK-NEXT: C1a.f()
152+
// CHECK-NEXT: C1a.g()
153+
// CHECK-NEXT: C1b.subscript()
154+
// CHECK-NEXT: C1a.p
155+
// CHECK-NEXT: } callDynamicSelfExistential
156+
callDynamicSelfExistential(C1b())
157+
158+
// CHECK-NEXT: callDynamicSelfExistential {
159+
// CHECK-NEXT: [Self := C2a, self is C2b] P extension.f()
160+
// CHECK-NEXT: [Self := C2a, self is C2b] P extension.g()
161+
// CHECK-NEXT: [Self := C2a, self is C2b] P extension.subscript()
162+
// CHECK-NEXT: [Self := C2a, self is C2b] P extension.p
163+
// CHECK-NEXT: } callDynamicSelfExistential
164+
callDynamicSelfExistential(C2b() as C2a)
165+
166+
// CHECK-NEXT: callDynamicSelfClassExistential {
167+
// CHECK-NEXT: C1a.f()
168+
// CHECK-NEXT: C1a.g()
169+
// CHECK-NEXT: C1a.subscript()
170+
// CHECK-NEXT: C1a.p
171+
// CHECK-NEXT: } callDynamicSelfClassExistential
172+
callDynamicSelfClassExistential(C1a())
173+
174+
// CHECK-NEXT: callDynamicSelfClassExistential {
175+
// CHECK-NEXT: [Self := C3b, self is C3b] CP extension.f()
176+
// CHECK-NEXT: [Self := C3b, self is C3b] CP extension.g()
177+
// CHECK-NEXT: [Self := C3b, self is C3b] CP extension.subscript()
178+
// CHECK-NEXT: [Self := C3b, self is C3b] CP extension.p
179+
// CHECK-NEXT: } callDynamicSelfClassExistential
180+
callDynamicSelfClassExistential(C3b() as C3a)
90181

91182
print("-------------------------------")
92183

test/SILGen/dynamic_self.swift

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@
88

99
protocol P {
1010
func f() -> Self
11+
subscript() -> Self { get }
12+
var p: Self { get }
1113
}
1214

1315
protocol CP : class {
1416
func f() -> Self
17+
subscript() -> Self { get }
18+
var p: Self { get }
1519
}
1620

1721
class X : P, CP {
@@ -20,6 +24,12 @@ class X : P, CP {
2024
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self1XC1f{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed X) -> @owned
2125
func f() -> Self { return self }
2226

27+
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self1XCACXDycig : $@convention(method) (@guaranteed X) -> @owned X
28+
subscript() -> Self { self }
29+
30+
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self1XC1pACXDvg : $@convention(method) (@guaranteed X) -> @owned X
31+
var p: Self { self }
32+
2333
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self1XC7factory{{[_0-9a-zA-Z]*}}FZ : $@convention(method) (Int, @thick X.Type) -> @owned X
2434
// CHECK: bb0([[I:%[0-9]+]] : $Int, [[SELF:%[0-9]+]] : $@thick X.Type):
2535
// CHECK: [[DYNAMIC_SELF:%[0-9]+]] = unchecked_trivial_bit_cast [[SELF]] : $@thick X.Type to $@thick @dynamic_self X.Type
@@ -83,17 +93,65 @@ func testExistentialDispatch(p: P) {
8393
// CHECK: destroy_addr [[P_RESULT]] : $*P
8494
// CHECK: dealloc_stack [[P_RESULT]] : $*P
8595
_ = p.f()
96+
97+
// CHECK: [[PCOPY_ADDR:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P to $*@opened([[N:".*"]]) P
98+
// CHECK: [[P_RESULT:%[0-9]+]] = alloc_stack $P
99+
// CHECK: [[PCOPY_ADDR_1:%[0-9]+]] = alloc_stack $@opened([[N]]) P
100+
// CHECK: copy_addr [[PCOPY_ADDR]] to [initialization] [[PCOPY_ADDR_1]] : $*@opened([[N]]) P
101+
// CHECK: [[P_P_GETTER:%[0-9]+]] = witness_method $@opened([[N]]) P, #P.p!getter : {{.*}}, [[PCOPY_ADDR]]{{.*}} : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
102+
// CHECK: [[P_RESULT_ADDR2:%[0-9]+]] = init_existential_addr [[P_RESULT]] : $*P, $@opened([[N]]) P
103+
// CHECK: apply [[P_P_GETTER]]<@opened([[N]]) P>([[P_RESULT_ADDR2]], [[PCOPY_ADDR_1]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
104+
// CHECK: destroy_addr [[PCOPY_ADDR_1]] : $*@opened([[N]]) P
105+
// CHECK: destroy_addr [[P_RESULT]] : $*P
106+
// CHECK: dealloc_stack [[PCOPY_ADDR_1]] : $*@opened([[N]]) P
107+
// CHECK: dealloc_stack [[P_RESULT]] : $*P
108+
_ = p.p
109+
110+
// CHECK: [[PCOPY_ADDR:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P to $*@opened([[N:".*"]]) P
111+
// CHECK: [[P_RESULT:%[0-9]+]] = alloc_stack $P
112+
// CHECK: [[PCOPY_ADDR_1:%[0-9]+]] = alloc_stack $@opened([[N]]) P
113+
// CHECK: copy_addr [[PCOPY_ADDR]] to [initialization] [[PCOPY_ADDR_1]] : $*@opened([[N]]) P
114+
// CHECK: [[P_SUBSCRIPT_GETTER:%[0-9]+]] = witness_method $@opened([[N]]) P, #P.subscript!getter : {{.*}}, [[PCOPY_ADDR]]{{.*}} : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
115+
// CHECK: [[P_RESULT_ADDR:%[0-9]+]] = init_existential_addr [[P_RESULT]] : $*P, $@opened([[N]]) P
116+
// CHECK: apply [[P_SUBSCRIPT_GETTER]]<@opened([[N]]) P>([[P_RESULT_ADDR]], [[PCOPY_ADDR_1]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
117+
// CHECK: destroy_addr [[PCOPY_ADDR_1]] : $*@opened([[N]]) P
118+
// CHECK: destroy_addr [[P_RESULT]] : $*P
119+
// CHECK: dealloc_stack [[PCOPY_ADDR_1]] : $*@opened([[N]]) P
120+
// CHECK: dealloc_stack [[P_RESULT]] : $*P
121+
_ = p[]
86122
}
87123

88124
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self28testExistentialDispatchClass{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@guaranteed CP) -> ()
125+
func testExistentialDispatchClass(cp: CP) {
89126
// CHECK: bb0([[CP:%[0-9]+]] : @guaranteed $CP):
90127
// CHECK: [[CP_ADDR:%[0-9]+]] = open_existential_ref [[CP]] : $CP to $@opened([[N:".*"]]) CP
91128
// CHECK: [[CP_F:%[0-9]+]] = witness_method $@opened([[N]]) CP, #CP.f : {{.*}}, [[CP_ADDR]]{{.*}} : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0
92129
// CHECK: [[CP_F_RESULT:%[0-9]+]] = apply [[CP_F]]<@opened([[N]]) CP>([[CP_ADDR]]) : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0
93130
// CHECK: [[RESULT_EXISTENTIAL:%[0-9]+]] = init_existential_ref [[CP_F_RESULT]] : $@opened([[N]]) CP : $@opened([[N]]) CP, $CP
94131
// CHECK: destroy_value [[RESULT_EXISTENTIAL]]
95-
func testExistentialDispatchClass(cp: CP) {
96132
_ = cp.f()
133+
134+
// CHECK: [[CP_ADDR:%[0-9]+]] = open_existential_ref [[CP]] : $CP to $@opened([[N:".*"]]) CP
135+
// CHECK: [[CP_ADDR_1:%[0-9]+]] = copy_value [[CP_ADDR]] : $@opened([[N]]) CP
136+
// CHECK: [[CP_BORROWED:%[0-9]+]] = begin_borrow [[CP_ADDR_1]] : $@opened([[N]]) CP
137+
// CHECK: [[CP_P_GETTER:%[0-9]+]] = witness_method $@opened([[N]]) CP, #CP.p!getter : {{.*}}, [[CP_ADDR]]{{.*}} : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0
138+
// CHECK: [[APPLY_RESULT:%[0-9]+]] = apply [[CP_P_GETTER]]<@opened([[N]]) CP>([[CP_BORROWED]]) : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0
139+
// CHECK: end_borrow [[CP_BORROWED]] : $@opened([[N]]) CP
140+
// CHECK: destroy_value [[CP_ADDR_1]] : $@opened([[N]]) CP
141+
// CHECK: [[RESULT_EXISTENTIAL:%[0-9]+]] = init_existential_ref [[APPLY_RESULT]] : $@opened([[N]]) CP : $@opened([[N]]) CP, $CP
142+
// CHECK: destroy_value [[RESULT_EXISTENTIAL]] : $CP
143+
_ = cp.p
144+
145+
// CHECK: [[CP_ADDR:%[0-9]+]] = open_existential_ref [[CP]] : $CP to $@opened([[N:".*"]]) CP
146+
// CHECK: [[CP_ADDR_1:%[0-9]+]] = copy_value [[CP_ADDR]] : $@opened([[N]]) CP
147+
// CHECK: [[CP_BORROWED:%[0-9]+]] = begin_borrow [[CP_ADDR_1]] : $@opened([[N]]) CP
148+
// CHECK: [[CP_SUBSCRIPT_GETTER:%[0-9]+]] = witness_method $@opened([[N]]) CP, #CP.subscript!getter : {{.*}}, [[CP_ADDR]]{{.*}} : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0
149+
// CHECK: [[APPLY_RESULT:%[0-9]+]] = apply [[CP_SUBSCRIPT_GETTER]]<@opened([[N]]) CP>([[CP_BORROWED]]) : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0
150+
// CHECK: end_borrow [[CP_BORROWED]] : $@opened([[N]]) CP
151+
// CHECK: destroy_value [[CP_ADDR_1]] : $@opened([[N]]) CP
152+
// CHECK: [[RESULT_EXISTENTIAL:%[0-9]+]] = init_existential_ref [[APPLY_RESULT]] : $@opened([[N]]) CP : $@opened([[N]]) CP, $CP
153+
// CHECK: destroy_value [[RESULT_EXISTENTIAL]] : $CP
154+
_ = cp[]
97155
}
98156

99157
@objc class ObjC {

0 commit comments

Comments
 (0)