Skip to content

Commit 663793e

Browse files
committed
[Tests] Add tests.
1 parent 2a3b4dd commit 663793e

File tree

6 files changed

+442
-24
lines changed

6 files changed

+442
-24
lines changed

test/Constraints/keypath.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ let some = Some(keyPath: \Demo.here)
4141
func testFunc() {
4242
let _: (S) -> Int = \.i
4343
_ = ([S]()).map(\.i)
44-
_ = \S.init // expected-error {{key path cannot refer to initializer 'init()'}}
45-
_ = ([S]()).map(\.init) // expected-error {{key path cannot refer to initializer 'init()'}}
44+
_ = \S.Type.init
45+
_ = \S.init // expected-error {{static member 'init()' cannot be used on instance of type 'S'}}
46+
_ = ([S.Type]()).map(\.init)
47+
_ = ([S]()).map(\.init) // expected-error {{static member 'init()' cannot be used on instance of type 'S'}}
4648

4749
let kp = \S.i
4850
let _: KeyPath<S, Int> = kp // works, because type defaults to KeyPath nominal

test/Interpreter/keypath.swift

Lines changed: 199 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,30 @@
55
// UNSUPPORTED: use_os_stdlib
66
// UNSUPPORTED: back_deployment_runtime
77

8-
class MyLabel {
8+
class MyLabel: Hashable {
99
var text = "label"
1010
static var isVisible = true
11+
func x(val value: Int) -> Int { return value }
12+
static func y(val value: Int) -> Int { return value }
13+
func saveClosure(_ closure: @escaping () -> Void) {
14+
storedClosure = closure
15+
}
16+
func executeStoredClosure() {
17+
storedClosure?()
18+
}
19+
private var storedClosure: (() -> Void)?
20+
21+
required init() {}
22+
required init(customText: String) {
23+
text = customText
24+
}
25+
26+
static func == (lhs: MyLabel, rhs: MyLabel) -> Bool {
27+
return lhs === rhs
28+
}
29+
func hash(into hasher: inout Hasher) {
30+
hasher.combine(ObjectIdentifier(self))
31+
}
1132
}
1233

1334
class Controller {
@@ -57,11 +78,6 @@ class Controller {
5778
}
5879
}
5980

60-
struct S {
61-
var a: Int
62-
static let b: Double = 100.0
63-
}
64-
6581
struct Container<V> {
6682
var v : V
6783
init(_ v: V) {
@@ -70,16 +86,30 @@ struct Container<V> {
7086
func useKeyPath<V2: AnyObject>(_ keyPath: KeyPath<V, V2>) -> String {
7187
return (v[keyPath: keyPath] as! MyLabel).text
7288
}
89+
func invokeKeyPathMethod<V2, R>(
90+
_ keyPath: KeyPath<V, V2>,
91+
method: KeyPath<V2, (Int) -> R>,
92+
arg: Int
93+
) -> R {
94+
let instance = v[keyPath: keyPath]
95+
return instance[keyPath: method](arg)
96+
}
7397
}
7498

7599
extension Container where V: Controller {
76100
func test() -> String {
77101
return useKeyPath(\.label)
78102
}
103+
func testKeyPathMethod() -> Int {
104+
let result = invokeKeyPathMethod(\.label, method: \MyLabel.x(val:), arg: 10)
105+
return result
106+
}
79107
}
80108

81109
// CHECK: label
82110
print(Container(Controller()).test())
111+
// CHECK: 10
112+
print(Container(Controller()).testKeyPathMethod())
83113

84114
struct MetatypeContainer<V> {
85115
var v : V.Type
@@ -92,10 +122,38 @@ struct MetatypeContainer<V> {
92122
}
93123
return false
94124
}
125+
func getKeyPathMethodVal() -> Int {
126+
if let labelType = v as? MyLabel.Type {
127+
return labelType.y(val: 20)
128+
}
129+
return 0
130+
}
131+
func createInstanceWithDefaultInit() -> MyLabel? {
132+
if let labelType = v as? MyLabel.Type {
133+
return labelType.init()
134+
}
135+
return nil
136+
}
137+
func createInstanceWithCustomInit(customText: String) -> MyLabel? {
138+
if let labelType = v as? MyLabel.Type {
139+
return labelType.init(customText: customText)
140+
}
141+
return nil
142+
}
95143
}
96144

97145
// CHECK: true
98146
print(MetatypeContainer(MyLabel.self).useMetatypeKeyPath())
147+
// CHECK: 20
148+
print(MetatypeContainer(MyLabel.self).getKeyPathMethodVal())
149+
// CHECK: label
150+
if let instance = MetatypeContainer(MyLabel.self).createInstanceWithDefaultInit() {
151+
print(instance.text)
152+
}
153+
// CHECK: Custom Label
154+
if let customInstance = MetatypeContainer(MyLabel.self).createInstanceWithCustomInit(customText: "Custom Label") {
155+
print(customInstance.text)
156+
}
99157

100158
public class GenericController<U> {
101159
init(_ u: U) {
@@ -116,13 +174,28 @@ public func generic_class_constrained_keypath<U, V>(_ c: V) where V : GenericCon
116174
// CHECK: label
117175
generic_class_constrained_keypath(GenericController(5))
118176

177+
struct S {
178+
var year = 2024
179+
static let millenium: Int = 3
180+
init() {}
181+
init(val value: Int = 2024) { year = value }
182+
183+
var add: (Int, Int) -> Int { return { $0 + $1 } }
184+
func add(this: Int) -> Int { this + this}
185+
func add(that: Int) -> Int { that + that }
186+
static func subtract(_ val: Int) -> Int { return millenium - val }
187+
nonisolated func nonisolatedNextYear() -> Int { year + 1 }
188+
consuming func consume() { print(year) }
189+
subscript(index: Int) -> Int { return year + index}
190+
}
191+
119192
// CHECK: {{\\Controller\.secondLabel!\.text|\\Controller\.<computed 0x.* \(Optional<MyLabel>\)>!\.<computed 0x.* \(String\)>}}
120193
print(\Controller.secondLabel!.text)
121194

122195
// CHECK: {{\\Controller\.subscript\(_: String\)|\\Controller\.<computed 0x.* \(String\)>}}
123196
print(\Controller["abc"])
124-
// CHECK: \S.a
125-
print(\S.a)
197+
// CHECK: \S.year
198+
print(\S.year)
126199
// CHECK: {{\\Controller\.subscript\(int: Int, str: String, _: Int\)|\\Controller\.<computed 0x.* \(Int\)>}}
127200
print(\Controller[int: 0, str: "", 0])
128201
// CHECK: {{\\Controller\.thirdLabel|\\Controller\.<computed 0x.* \(Optional<MyLabel>\)>}}
@@ -146,11 +219,82 @@ print(\Controller[array: [42], array2: [42]])
146219
// CHECK: {{\\Controller\.(fourthLabel|<computed .* \(Optional<MyLabel\.Type>\)>)!\.<computed .* \(Bool\)>}}
147220
print(\Controller.fourthLabel!.isVisible)
148221

149-
// CHECK: \S.Type.<computed {{.*}} (Double)>
150-
print(\S.Type.b)
222+
// CHECK: \S.Type.<computed {{.*}} (Int)>
223+
print(\S.Type.millenium)
151224
// CHECK: {{\\Controller\.(fifthLabel|<computed .* \(Optional<MyLabel\.Type>\)>)\?\.<computed .* \(Bool\)>?}}
152225
print(\Controller.fifthLabel?.isVisible)
153226

227+
// CHECK: \S.Type.<computed {{.*}} (() -> S)>
228+
print(\S.Type.init)
229+
// CHECK: \S.Type.<computed {{.*}} (S)>
230+
print(\S.Type.init())
231+
// CHECK: \S.Type.<computed {{.*}} ((Int) -> S)>
232+
print(\S.Type.init(val:))
233+
// CHECK: \S.Type.<computed {{.*}} (S)>
234+
print(\S.Type.init(val: 2025))
235+
// CHECK: \S.Type.<computed {{.*}} (S)>.year
236+
print(\S.Type.init(val: 2025).year)
237+
// CHECK: \S.Type.<computed {{.*}} (S)>.subscript(_: Int)
238+
print(\S.Type.init()[0])
239+
// CHECK: \S.add
240+
print(\S.add)
241+
// CHECK: \S.<computed {{.*}} ((Int) -> Int)>
242+
print(\S.add(this:))
243+
// CHECK: \S.<computed {{.*}} (Int)>
244+
print(\S.add(that: 1))
245+
// CHECK: \S.Type.<computed {{.*}} ((Int) -> Int)>
246+
print(\S.Type.subtract)
247+
// CHECK: \S.Type.<computed {{.*}} (Int)>
248+
print(\S.Type.subtract(1))
249+
// CHECK: \S.<computed {{.*}} (() -> Int)>
250+
print(\S.nonisolatedNextYear)
251+
// CHECK: \S.<computed {{.*}} (Int)>
252+
print(\S.nonisolatedNextYear())
253+
// CHECK: \S.Type.<computed {{.*}} (S)>.<computed {{.*}} (Int)>
254+
print(\S.Type.init(val:2025).nonisolatedNextYear())
255+
// CHECK: \S.Type.<computed {{.*}} (S)>.<computed {{.*}} (Int)>.description
256+
print(\S.Type.init(val:2025).nonisolatedNextYear().description)
257+
// CHECK: \S.Type.<computed {{.*}} (S)>.<computed {{.*}} (Int)>.<computed {{.*}} (Int)>
258+
print(\S.Type.init(val:2025).nonisolatedNextYear().signum())
259+
// // CHECK: \S.<computed {{.*}} (())>
260+
print(\S.consume())
261+
262+
// CHECK: false
263+
print(\S.add(that: 1) == \S.add(this: 1))
264+
// CHECK: false
265+
print(\S.add(that: 1) == \S.add(this: 2))
266+
// CHECK: false
267+
print(\S.Type.init(val: 2024) == \S.Type.init(val: 2025))
268+
// CHECK: false
269+
print(\S.Type.init(val: 2024).nonisolatedNextYear() == \S.Type.init(val: 2025))
270+
// CHECK: true
271+
print(\S.Type.init(val: 2024).add(this: 1) != \S.Type.init(val: 2025))
272+
273+
class E: Hashable {
274+
static func == (lhs: E, rhs: E) -> Bool { return lhs === rhs }
275+
func hash(into hasher: inout Hasher) {
276+
hasher.combine(ObjectIdentifier(self))
277+
}
278+
private var storedClosure: (() -> Void)?
279+
func saveClosure(_ closure: @escaping () -> Void) { storedClosure = closure }
280+
}
281+
struct BaseType {
282+
func foo(hashableParam e: E) {}
283+
}
284+
let hashableInstance = E()
285+
// CHECK: \BaseType.<computed {{.*}} (())>
286+
print(\BaseType.foo(hashableParam: hashableInstance))
287+
288+
// CHECK: false
289+
print(\S.Type.init(val:2025) == \S.Type.init(val:2026))
290+
// CHECK: false
291+
print(\S.Type.init(val:2025).nonisolatedNextYear() == \S.Type.init(val:2026).nonisolatedNextYear())
292+
// CHECK: true
293+
print(\S.Type.init(val:2025).nonisolatedNextYear() == \S.Type.init(val:2025).nonisolatedNextYear())
294+
// CHECK: false
295+
print(\MyLabel.x(val:10) == \MyLabel.x(val:20))
296+
// CHECK: true
297+
print(\MyLabel.Type.y(val:10) == \MyLabel.Type.y(val:10))
154298

155299
do {
156300
struct S {
@@ -206,3 +350,48 @@ do {
206350
// CHECK: true
207351
print(StaticExample<MyLabel>().isVisible)
208352
}
353+
354+
do {
355+
@dynamicMemberLookup
356+
struct InstanceDynamicMemberLookup<T> {
357+
var obj: T
358+
359+
subscript<U>(dynamicMember member: KeyPath<T, (Int) -> U>) -> (Int) -> U {
360+
get { obj[keyPath: member] }
361+
}
362+
}
363+
364+
// CHECK: 50
365+
let instanceDynamicLookup = InstanceDynamicMemberLookup(obj: MyLabel())
366+
print(instanceDynamicLookup.x(50))
367+
}
368+
369+
extension MyLabel {
370+
static var defaultInitializer: () -> MyLabel { return MyLabel.init }
371+
static var customInitializer: (String) -> MyLabel { return MyLabel.init(customText:) }
372+
}
373+
374+
do {
375+
@dynamicMemberLookup
376+
struct StaticDynamicMemberLookup<T> {
377+
subscript<U>(dynamicMember keyPath: KeyPath<T.Type, (Int) -> U>) -> (Int) -> U {
378+
return T.self[keyPath: keyPath]
379+
}
380+
subscript<U>(dynamicMember keyPath: KeyPath<T.Type, () -> U>) -> () -> U {
381+
return T.self[keyPath: keyPath]
382+
}
383+
subscript<U>(dynamicMember keyPath: KeyPath<T.Type, (String) -> U>) -> (String) -> U {
384+
return T.self[keyPath: keyPath]
385+
}
386+
}
387+
388+
// CHECK: 60
389+
let staticDynamicLookup = StaticDynamicMemberLookup<MyLabel>()
390+
print(staticDynamicLookup.y(60))
391+
// CHECK: label
392+
let defaultInstance = staticDynamicLookup.defaultInitializer()
393+
print(defaultInstance.text)
394+
// CHECK: Custom Label
395+
let customInstance = staticDynamicLookup.customInitializer("Custom Label")
396+
print(customInstance.text)
397+
}

test/Interpreter/static_keypaths.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ public struct AStruct {
3030
public static var property2: Int = 2
3131
private(set) public static var property3: Int = 1
3232
private(set) public static var property4: Int = 4
33+
public static func x(val value: Int) -> Int { return value }
34+
public static func y(val value: Int) -> Int { return value }
35+
36+
public init(val value: Int = 2024) {
37+
year = value
38+
}
39+
public var year: Int
3340
}
3441

3542
//--- LibB.swift
@@ -40,6 +47,10 @@ public let keyPath2FromLibB = \AStruct.Type.property2
4047
public let keyPath3FromLibB = \AStruct.Type.property3
4148
public let keyPath4FromLibB = \AStruct.Type.property4
4249
public var keyPath5FromLibB = \AStruct.Type.property1 // WritableKeyPath with public setter
50+
public let keyPath6FromLibB = \AStruct.Type.x(val: 10)
51+
public let keyPath7FromLibB = \AStruct.Type.y(val: 10)
52+
public let keyPath8FromLibB = \AStruct.Type.init
53+
public let keyPath9FromLibB = \AStruct.Type.init(val: 2025)
4354

4455
//--- LibC.swift
4556
import LibA
@@ -48,6 +59,9 @@ public let keyPath1FromLibC = \AStruct.Type.property1
4859
public let keyPath2FromLibC = \AStruct.Type.property2
4960
public let keyPath3FromLibC = \AStruct.Type.property3 // Read-only with private setter
5061
public let keyPath4FromLibC = \AStruct.Type.property4
62+
public let keyPath5FromLibC = \AStruct.Type.x(val: 10)
63+
public let keyPath6FromLibC = \AStruct.Type.init
64+
public let keyPath7FromLibC = \AStruct.Type.init(val: 2026)
5165

5266
//--- main.swift
5367
import LibB
@@ -65,3 +79,15 @@ print(keyPath3FromLibB != keyPath4FromLibC)
6579

6680
// CHECK: false
6781
print(keyPath5FromLibB == keyPath3FromLibC)
82+
83+
// CHECK: true
84+
print(keyPath6FromLibB == keyPath5FromLibC)
85+
// CHECK: false
86+
print(keyPath7FromLibB == keyPath5FromLibC)
87+
88+
// CHECK: true
89+
print(keyPath8FromLibB == keyPath6FromLibC)
90+
// CHECK: false
91+
print(keyPath9FromLibB == keyPath7FromLibC)
92+
// CHECK: true
93+
print(keyPath9FromLibB != keyPath7FromLibC)

0 commit comments

Comments
 (0)