Skip to content

Commit 1577afe

Browse files
technicatedToma91
authored andcommitted
Added more tests (related to generic tuples)
1 parent b0e424f commit 1577afe

File tree

7 files changed

+194
-114
lines changed

7 files changed

+194
-114
lines changed

lib/IRGen/GenKeyPath.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,9 @@ emitKeyPathComponent(IRGenModule &IGM,
11151115
//
11161116
// This code is ALSO executed in the case of a tuple with dynamic layout,
11171117
// (see below) but only if `component.getTupleIndex()` is 0 - in that case
1118-
// the compiler knows that the tuple element is always at offset 0
1118+
// the compiler knows that the tuple element is always at offset 0.
1119+
// TODO: If this is behavior is not desired we should find a way to skip to
1120+
// the next section of code e.g. check if baseTy has archetypes?
11191121
if (auto offset = getFixedTupleElementOffset(IGM, loweredTy, component.getTupleIndex())) {
11201122
auto header = KeyPathComponentHeader
11211123
::forStructComponentWithInlineOffset(/*isLet*/ false,

test/IRGen/keypaths.sil

Lines changed: 74 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,15 @@ public class C2: C1 {
4040

4141
public struct T {
4242
public var a: (Int, String)
43-
public let b: (String, Int)
44-
public var c: (f: Int, g: String)
45-
public let d: (x: String, y: Int)
43+
public let b: (f: String, g: Int)
4644
}
4745

46+
public struct TG<T, U, V> {
47+
public var a: (T, U, V)
48+
}
49+
50+
typealias TGA<T, U> = (a: T, b: U)
51+
4852
sil_vtable C {}
4953
sil_vtable C1 {}
5054
sil_vtable C2 {}
@@ -200,41 +204,13 @@ sil_vtable C2 {}
200204
// -- tuple element #0 of T.a
201205
// CHECK-SAME: <i32 0x0180_0000> }>
202206

203-
// -- %t1: T.a.1
207+
// -- %t1: T.b.g
204208
// CHECK: [[KP_T1:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
205209
// CHECK-SAME: [[WORD]]* @keypath_once
206210
// CHECK-SAME: @"symbolic
207211
// CHECK-SAME: @"symbolic
208212
// -- instantiable in-line, size 12
209213
// CHECK-SAME: <i32 0x8000_000c>,
210-
// -- offset of T.a, mutable
211-
// CHECK-SAME: <i32 0x0180_0000>,
212-
// CHECK: @"symbolic
213-
// -- tuple element #1 of T.a
214-
// CHECK-32-SAME: <i32 0x0180_0004> }>
215-
// CHECK-64-SAME: <i32 0x0180_0008> }>
216-
217-
// -- %t2: T.b.0
218-
// CHECK: [[KP_T2:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
219-
// CHECK-SAME: [[WORD]]* @keypath_once
220-
// CHECK-SAME: @"symbolic
221-
// CHECK-SAME: @"symbolic
222-
// -- instantiable in-line, size 12
223-
// CHECK-SAME: <i32 0x8000_000c>,
224-
// -- offset of T.b
225-
// CHECK-32-SAME: <i32 0x0100_000c>,
226-
// CHECK-64-SAME: <i32 0x0100_0018>,
227-
// CHECK: @"symbolic
228-
// -- tuple element #0 of T.b
229-
// CHECK-SAME: <i32 0x0180_0000> }>
230-
231-
// -- %t3: T.b.1
232-
// CHECK: [[KP_T3:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
233-
// CHECK-SAME: [[WORD]]* @keypath_once
234-
// CHECK-SAME: @"symbolic
235-
// CHECK-SAME: @"symbolic
236-
// -- instantiable in-line, size 12
237-
// CHECK-SAME: <i32 0x8000_000c>,
238214
// -- offset of T.b
239215
// CHECK-32-SAME: <i32 0x0100_000c>,
240216
// CHECK-64-SAME: <i32 0x0100_0018>,
@@ -243,65 +219,6 @@ sil_vtable C2 {}
243219
// CHECK-32-SAME: <i32 0x0180_0008> }>
244220
// CHECK-64-SAME: <i32 0x0180_0010> }>
245221

246-
// -- %t4: T.c.f
247-
// CHECK: [[KP_T4:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
248-
// CHECK-SAME: [[WORD]]* @keypath_once
249-
// CHECK-SAME: @"symbolic
250-
// CHECK-SAME: @"symbolic
251-
// -- instantiable in-line, size 12
252-
// CHECK-SAME: <i32 0x8000_000c>,
253-
// -- offset of T.f, mutable
254-
// CHECK-32-SAME: <i32 0x0180_0018>,
255-
// CHECK-64-SAME: <i32 0x0180_0030>,
256-
// CHECK: @"symbolic
257-
// -- tuple element #0 of T.f
258-
// CHECK-SAME: <i32 0x0180_0000> }>
259-
260-
// -- %t5: T.c.g
261-
// CHECK: [[KP_T5:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
262-
// CHECK-SAME: [[WORD]]* @keypath_once
263-
// CHECK-SAME: @"symbolic
264-
// CHECK-SAME: @"symbolic
265-
// -- instantiable in-line, size 12
266-
// CHECK-SAME: <i32 0x8000_000c>,
267-
// -- offset of T.f, mutable
268-
// CHECK-32-SAME: <i32 0x0180_0018>,
269-
// CHECK-64-SAME: <i32 0x0180_0030>,
270-
// CHECK: @"symbolic
271-
// -- tuple element #1 of T.f
272-
// CHECK-32-SAME: <i32 0x0180_0004> }>
273-
// CHECK-64-SAME: <i32 0x0180_0008> }>
274-
275-
// -- %t6: T.d.x
276-
// CHECK: [[KP_T6:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
277-
// CHECK-SAME: [[WORD]]* @keypath_once
278-
// CHECK-SAME: @"symbolic
279-
// CHECK-SAME: @"symbolic
280-
// -- instantiable in-line, size 12
281-
// CHECK-SAME: <i32 0x8000_000c>,
282-
// -- offset of T.d
283-
// CHECK-32-SAME: <i32 0x0100_0024>,
284-
// CHECK-64-SAME: <i32 0x0100_0048>,
285-
// CHECK: @"symbolic
286-
// -- tuple element #0 of T.d
287-
// CHECK-32-SAME: <i32 0x0180_0000> }>
288-
// CHECK-64-SAME: <i32 0x0180_0000> }>
289-
290-
// -- %t7: T.d.y
291-
// CHECK: [[KP_T7:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
292-
// CHECK-SAME: [[WORD]]* @keypath_once
293-
// CHECK-SAME: @"symbolic
294-
// CHECK-SAME: @"symbolic
295-
// -- instantiable in-line, size 12
296-
// CHECK-SAME: <i32 0x8000_000c>,
297-
// -- offset of T.d
298-
// CHECK-32-SAME: <i32 0x0100_0024>,
299-
// CHECK-64-SAME: <i32 0x0100_0048>,
300-
// CHECK: @"symbolic
301-
// -- tuple element #0 of T.d
302-
// CHECK-32-SAME: <i32 0x0180_0008> }>
303-
// CHECK-64-SAME: <i32 0x0180_0010> }>
304-
305222
// -- %i: Gen<A>.x
306223
// CHECK: [[KP_I:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
307224
// CHECK-SAME: i32 0
@@ -328,6 +245,49 @@ sil_vtable C2 {}
328245
// CHECK-32-SAME: i32 20 }>
329246
// CHECK-64-SAME: i32 36 }>
330247

248+
// -- %tg0: TG<T,U,V>.a.0
249+
// CHECK: [[KP_TG0:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
250+
// CHECK-SAME: @"generic environment r1_l"
251+
// CHECK-SAME: @"symbolic
252+
// CHECK-SAME: @"symbolic
253+
// -- struct with runtime-resolved offset, mutable
254+
// CHECK-SAME: <i32 0x01ff_fffe>,
255+
// -- offset of TG.a
256+
// CHECK-32-SAME: i32 20
257+
// CHECK-64-SAME: i32 40
258+
// CHECK-SAME: @"symbolic
259+
// -- tuple element with compile-time known offset, mutable
260+
// -- tuple element #0 of TG.a
261+
// CHECK-SAME: <i32 0x0180_0000> }>
262+
263+
// -- %tg1: TG<T,U,V>.a.2
264+
// CHECK: [[KP_TG1:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
265+
// CHECK-SAME: @"generic environment r1_l"
266+
// CHECK-SAME: @"symbolic
267+
// CHECK-SAME: @"symbolic
268+
// -- struct with runtime-resolved offset, mutable
269+
// CHECK-SAME: <i32 0x01ff_fffe>,
270+
// -- offset of TG.a
271+
// CHECK-32-SAME: i32 20
272+
// CHECK-64-SAME: i32 40
273+
// CHECK-SAME: @"symbolic
274+
// -- tuple element with runtime-resolved offset, mutable
275+
// CHECK-SAME: <i32 0x01ff_fffe>,
276+
// -- tuple element #2 of TG.a
277+
// CHECK-32-SAME: i32 32 }>
278+
// CHECK-64-SAME: i32 64 }>
279+
280+
// -- %tg2: TGA<T,U>.1
281+
// CHECK: [[KP_TG2:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
282+
// CHECK-SAME: @"generic environment r0_l"
283+
// CHECK-SAME: @"symbolic
284+
// CHECK-SAME: @"symbolic
285+
// -- tuple element with runtime-resolved offset, mutable
286+
// CHECK-SAME: <i32 0x01ff_fffe>,
287+
// -- tuple element #1 of TGA
288+
// CHECK-32-SAME: i32 24 }>
289+
// CHECK-64-SAME: i32 48 }>
290+
331291
// CHECK-LABEL: @"generic environment SHRzSHR_r0_l" = linkonce_odr hidden constant
332292
// CHECK-SAME: i32 8193, i16 2, i8 -128, i8 -128, i32 128
333293

@@ -360,23 +320,9 @@ entry:
360320

361321
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_T0]] to i8*), i8* undef)
362322
%t0 = keypath $KeyPath<T, Int>, (root $T; stored_property #T.a : $(Int, String); tuple_element #0 : $Int)
363-
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_T1]] to i8*), i8* undef)
364-
%t1 = keypath $KeyPath<T, String>, (root $T; stored_property #T.a : $(Int, String); tuple_element #1 : $String)
365-
366-
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_T2]] to i8*), i8* undef)
367-
%t2 = keypath $KeyPath<T, String>, (root $T; stored_property #T.b : $(String, Int); tuple_element #0 : $String)
368-
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_T3]] to i8*), i8* undef)
369-
%t3 = keypath $KeyPath<T, Int>, (root $T; stored_property #T.b : $(String, Int); tuple_element #1 : $Int)
370323

371-
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_T4]] to i8*), i8* undef)
372-
%t4 = keypath $KeyPath<T, Int>, (root $T; stored_property #T.c : $(f: Int, g: String); tuple_element #0 : $Int)
373-
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_T5]] to i8*), i8* undef)
374-
%t5 = keypath $KeyPath<T, String>, (root $T; stored_property #T.c : $(f: Int, g: String); tuple_element #1 : $String)
375-
376-
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_T6]] to i8*), i8* undef)
377-
%t6 = keypath $KeyPath<T, String>, (root $T; stored_property #T.d : $(x: String, y: Int); tuple_element #0 : $String)
378-
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_T7]] to i8*), i8* undef)
379-
%t7 = keypath $KeyPath<T, Int>, (root $T; stored_property #T.d : $(x: String, y: Int); tuple_element #1 : $Int)
324+
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_T1]] to i8*), i8* undef)
325+
%t1 = keypath $KeyPath<T, Int>, (root $T; stored_property #T.b : $(f: String, g: Int); tuple_element #1 : $Int)
380326

381327
return undef : $()
382328
}
@@ -442,6 +388,27 @@ entry:
442388
return undef : $()
443389
}
444390

391+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @tuple_generics(%swift.type* %T, %swift.type* %U, %swift.type* %V)
392+
sil @tuple_generics : $@convention(thin) <T, U, V> () -> () {
393+
entry:
394+
// CHECK: [[PTR:%.*]] = bitcast i8* [[ARGS:%.*]] to
395+
// CHECK: store %swift.type* %T, %swift.type** [[PTR]]
396+
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_TG0]] to i8*), i8* [[ARGS]])
397+
%tg0 = keypath $KeyPath<TG<T,U,V>, T>, <A,B,C> (root $TG<A,B,C>; stored_property #TG.a : $(A,B,C); tuple_element #0 : $A) <T,U,V>
398+
399+
// CHECK: [[PTR:%.*]] = bitcast i8* [[ARGS:%.*]] to
400+
// CHECK: store %swift.type* %T, %swift.type** [[PTR]]
401+
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_TG1]] to i8*), i8* [[ARGS]])
402+
%tg1 = keypath $KeyPath<TG<T,U,V>, V>, <A,B,C> (root $TG<A,B,C>; stored_property #TG.a : $(A,B,C); tuple_element #2 : $C) <T,U,V>
403+
404+
// CHECK: [[PTR:%.*]] = bitcast i8* [[ARGS:%.*]] to
405+
// CHECK: store %swift.type* %T, %swift.type** [[PTR]]
406+
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_TG2]] to i8*), i8* [[ARGS]])
407+
%tg2 = keypath $KeyPath<TGA<T,U>, U>, <A,B> (root $TGA<A,B>; tuple_element #1 : $B) <T,U>
408+
409+
return undef : $()
410+
}
411+
445412
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @computed_property_generics
446413
sil @computed_property_generics : $@convention(thin) <T, U> () -> () {
447414
entry:

test/SIL/Parser/keypath.sil

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,17 @@ entry:
135135
return undef : $()
136136
}
137137

138+
// CHECK-LABEL: sil shared @tuple_generic
139+
sil shared @ tuple_generic : $@convention(thin) <T, U> () -> () {
140+
entry:
141+
// CHECK: keypath $WritableKeyPath<(T, U), T>, <τ_0_0, τ_0_1> (root $(τ_0_0, τ_0_1); tuple_element #0 : $τ_0_0) <T, U>
142+
%a = keypath $WritableKeyPath<(T, U), T>, <τ_0_0, τ_0_1> (root $(τ_0_0, τ_0_1); tuple_element #0 : $τ_0_0) <T, U>
143+
// CHECK: keypath $WritableKeyPath<(T, U), U>, <τ_0_0, τ_0_1> (root $(τ_0_0, τ_0_1); tuple_element #1 : $τ_0_1) <T, U>
144+
%b = keypath $WritableKeyPath<(T, U), U>, <τ_0_0, τ_0_1> (root $(τ_0_0, τ_0_1); tuple_element #1 : $τ_0_1) <T, U>
145+
146+
return undef : $()
147+
}
148+
138149
// CHECK-LABEL: sil @optional
139150
sil @optional : $@convention(thin) () -> () {
140151
entry:

test/SIL/Serialization/keypath.sil

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,17 @@ entry:
9797
return undef : $()
9898
}
9999

100+
// CHECK-LABEL: sil shared [serialized] @tuple_generic
101+
sil shared [serialized] @tuple_generic : $@convention(thin) <T, U> () -> () {
102+
entry:
103+
// CHECK: keypath $WritableKeyPath<(T, U), T>, <τ_0_0, τ_0_1> (root $(τ_0_0, τ_0_1); tuple_element #0 : $τ_0_0) <T, U>
104+
%a = keypath $WritableKeyPath<(T, U), T>, <τ_0_0, τ_0_1> (root $(τ_0_0, τ_0_1); tuple_element #0 : $τ_0_0) <T, U>
105+
// CHECK: keypath $WritableKeyPath<(T, U), U>, <τ_0_0, τ_0_1> (root $(τ_0_0, τ_0_1); tuple_element #1 : $τ_0_1) <T, U>
106+
%b = keypath $WritableKeyPath<(T, U), U>, <τ_0_0, τ_0_1> (root $(τ_0_0, τ_0_1); tuple_element #1 : $τ_0_1) <T, U>
107+
108+
return undef : $()
109+
}
110+
100111
sil @id_a : $@convention(thin) () -> ()
101112
sil @get_s_int : $@convention(thin) (@in_guaranteed S) -> @out Int
102113
sil @set_s_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S) -> ()
@@ -184,11 +195,12 @@ entry:
184195
%0 = function_ref @stored_properties : $@convention(thin) () -> ()
185196
%1 = function_ref @stored_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> ()
186197
%2 = function_ref @tuple_elements : $@convention(thin) () -> ()
187-
%3 = function_ref @computed_properties : $@convention(thin) () -> ()
188-
%4 = function_ref @computed_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> ()
189-
%5 = function_ref @optional : $@convention(thin) () -> ()
190-
%6 = function_ref @indexes : $@convention(thin) (S, C) -> ()
191-
%7 = function_ref @external : $@convention(thin) <D: P, E: Q, F: R> () -> ()
198+
%3 = function_ref @tuple_generic : $@convention(thin) <T, U> () -> ()
199+
%4 = function_ref @computed_properties : $@convention(thin) () -> ()
200+
%5 = function_ref @computed_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> ()
201+
%6 = function_ref @optional : $@convention(thin) () -> ()
202+
%7 = function_ref @indexes : $@convention(thin) (S, C) -> ()
203+
%8 = function_ref @external : $@convention(thin) <D: P, E: Q, F: R> () -> ()
192204

193205
unreachable
194206
}

test/SILGen/keypaths.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,17 @@ func tuples(_: T) {
422422
// CHECK: keypath $KeyPath<T, String>, (root $T; stored_property #T.c : $(x: C<Int>, y: C<String>); tuple_element #0 : $C<Int>; stored_property #C.y : $String)
423423
let _: KeyPath<T, String> = \T.c.x.y
424424
}
425+
426+
// CHECK-LABEL: sil hidden @{{.*}}tuples_generic
427+
func tuples_generic<T, U, V>(_: T, _: U, _: V) {
428+
typealias TUC = (T, U, C<V>)
429+
430+
// CHECK: keypath $WritableKeyPath<(T, U, C<V>), T>, <τ_0_0, τ_0_1, τ_0_2> (root $(τ_0_0, τ_0_1, C<τ_0_2>); tuple_element #0 : $τ_0_0) <T, U, V>
431+
let _: WritableKeyPath<TUC, T> = \TUC.0
432+
// CHECK: keypath $WritableKeyPath<(T, U, C<V>), U>, <τ_0_0, τ_0_1, τ_0_2> (root $(τ_0_0, τ_0_1, C<τ_0_2>); tuple_element #1 : $τ_0_1) <T, U, V>
433+
let _: WritableKeyPath<TUC, U> = \TUC.1
434+
// CHECK: keypath $ReferenceWritableKeyPath<(T, U, C<V>), V>, <τ_0_0, τ_0_1, τ_0_2> (root $(τ_0_0, τ_0_1, C<τ_0_2>); tuple_element #2 : $C<τ_0_2>; stored_property #C.x : $τ_0_2) <T, U, V>
435+
let _: ReferenceWritableKeyPath<TUC, V> = \TUC.2.x
436+
// CHECK: keypath $KeyPath<(T, U, C<V>), String>, <τ_0_0, τ_0_1, τ_0_2> (root $(τ_0_0, τ_0_1, C<τ_0_2>); tuple_element #2 : $C<τ_0_2>; stored_property #C.y : $String) <T, U, V>
437+
let _: KeyPath<TUC, String> = \TUC.2.y
438+
}

test/expr/unary/keypath/keypath.swift

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,10 @@ struct TupleStruct {
232232
var labeled: (foo: Int, bar: String)
233233
}
234234

235-
func tupleComponent() {
235+
typealias UnlabeledGenericTuple<T, U> = (T, U)
236+
typealias LabeledGenericTuple<T, U> = (a: T, b: U)
237+
238+
func tupleComponent<T, U>(_: T, _: U) {
236239
let _ = \(Int, String).0
237240
let _ = \(Int, String).1
238241
let _ = \TupleStruct.unlabeled.0
@@ -246,6 +249,42 @@ func tupleComponent() {
246249
let _ = \TupleStruct.labeled.1
247250
let _ = \TupleStruct.labeled.foo
248251
let _ = \TupleStruct.labeled.bar
252+
253+
let _ = \(T, U).0
254+
let _ = \(T, U).1
255+
let _ = \UnlabeledGenericTuple<T, U>.0
256+
let _ = \UnlabeledGenericTuple<T, U>.1
257+
258+
let _ = \(a: T, b: U).0
259+
let _ = \(a: T, b: U).1
260+
let _ = \(a: T, b: U).a
261+
let _ = \(a: T, b: U).b
262+
let _ = \LabeledGenericTuple<T, U>.0
263+
let _ = \LabeledGenericTuple<T, U>.1
264+
let _ = \LabeledGenericTuple<T, U>.a
265+
let _ = \LabeledGenericTuple<T, U>.b
266+
}
267+
268+
func tuple_el_0<T, U>() -> KeyPath<(T, U), T> {
269+
return \.0
270+
}
271+
272+
func tuple_el_1<T, U>() -> KeyPath<(T, U), U> {
273+
return \.1
274+
}
275+
276+
func tupleGeneric<T, U>(_ v: (T, U)) {
277+
_ = (1, "hello")[keyPath: tuple_el_0()]
278+
_ = (1, "hello")[keyPath: tuple_el_1()]
279+
280+
_ = v[keyPath: tuple_el_0()]
281+
_ = v[keyPath: tuple_el_1()]
282+
283+
_ = ("tuple", "too", "big")[keyPath: tuple_el_1()]
284+
// expected-note@-12 {{}}
285+
// expected-error@-2 {{cannot be applied}}
286+
// expected-error@-3 {{cannot be applied}}
287+
// expected-error@-4 {{could not be inferred}}
249288
}
250289

251290
struct Z { }

0 commit comments

Comments
 (0)