Skip to content

Commit e32da1c

Browse files
committed
[Tests] Add tests.
1 parent 7c6743c commit e32da1c

File tree

8 files changed

+523
-25
lines changed

8 files changed

+523
-25
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: 209 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,13 +219,94 @@ 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
// CHECK: \Int.Type.<computed {{.*}} (Int)>
154227
print(\Int.Type.zero)
155228

229+
// CHECK: \S.Type.<computed {{.*}} (() -> S)>
230+
print(\S.Type.init)
231+
// CHECK: \S.Type.<computed {{.*}} (S)>
232+
print(\S.Type.init())
233+
// CHECK: \S.Type.<computed {{.*}} ((Int) -> S)>
234+
print(\S.Type.init(val:))
235+
// CHECK: \S.Type.<computed {{.*}} (S)>
236+
print(\S.Type.init(val: 2025))
237+
// CHECK: \S.Type.<computed {{.*}} (S)>.year
238+
print(\S.Type.init(val: 2025).year)
239+
// CHECK: 2024
240+
let kp = \S.Type.init()[0]
241+
let result = S.self[keyPath: kp]
242+
print(result)
243+
// CHECK: \S.add
244+
print(\S.add)
245+
// CHECK: \S.<computed {{.*}} ((Int) -> Int)>
246+
print(\S.add(this:))
247+
// CHECK: \S.<computed {{.*}} (Int)>
248+
print(\S.add(that: 1))
249+
// CHECK: \S.Type.<computed {{.*}} ((Int) -> Int)>
250+
print(\S.Type.subtract)
251+
// CHECK: \S.Type.<computed {{.*}} (Int)>
252+
print(\S.Type.subtract(1))
253+
// CHECK: \S.<computed {{.*}} (() -> Int)>
254+
print(\S.nonisolatedNextYear)
255+
// CHECK: \S.<computed {{.*}} (Int)>
256+
print(\S.nonisolatedNextYear())
257+
// CHECK: \S.Type.<computed {{.*}} (S)>.<computed {{.*}} (Int)>
258+
print(\S.Type.init(val:2025).nonisolatedNextYear())
259+
// CHECK: \S.Type.<computed {{.*}} (S)>.<computed {{.*}} (Int)>.description
260+
print(\S.Type.init(val:2025).nonisolatedNextYear().description)
261+
// CHECK: \S.Type.<computed {{.*}} (S)>.<computed {{.*}} (Int)>.<computed {{.*}} (Int)>
262+
print(\S.Type.init(val:2025).nonisolatedNextYear().signum())
263+
// // CHECK: \S.<computed {{.*}} (())>
264+
print(\S.consume())
265+
266+
// CHECK: false
267+
print(\S.add(that: 1) == \S.add(this: 1))
268+
// CHECK: false
269+
print(\S.add(that: 1) == \S.add(this: 2))
270+
// CHECK: false
271+
print(\S.Type.init(val: 2024) == \S.Type.init(val: 2025))
272+
// CHECK: false
273+
print(\S.Type.init(val: 2024).nonisolatedNextYear() == \S.Type.init(val: 2025))
274+
// CHECK: true
275+
print(\S.Type.init(val: 2024).add(this: 1) != \S.Type.init(val: 2025))
276+
277+
class E: Hashable {
278+
static func == (lhs: E, rhs: E) -> Bool { return lhs === rhs }
279+
func hash(into hasher: inout Hasher) {
280+
hasher.combine(ObjectIdentifier(self))
281+
}
282+
}
283+
struct BaseType {
284+
func foo(hashableParam e: E) {}
285+
}
286+
let hashableInstance = E()
287+
// CHECK: \BaseType.<computed {{.*}} (())>
288+
print(\BaseType.foo(hashableParam: hashableInstance))
289+
290+
protocol Describable {
291+
func describe() -> String
292+
}
293+
struct C: Describable {
294+
var name: String
295+
func describe() -> String { return "\(name)" }
296+
}
297+
// CHECK: \C.<computed {{.*}} (() -> String)>
298+
print(\C.describe)
299+
300+
// CHECK: false
301+
print(\S.Type.init(val:2025) == \S.Type.init(val:2026))
302+
// CHECK: false
303+
print(\S.Type.init(val:2025).nonisolatedNextYear() == \S.Type.init(val:2026).nonisolatedNextYear())
304+
// CHECK: true
305+
print(\S.Type.init(val:2025).nonisolatedNextYear() == \S.Type.init(val:2025).nonisolatedNextYear())
306+
// CHECK: false
307+
print(\MyLabel.x(val:10) == \MyLabel.x(val:20))
308+
// CHECK: true
309+
print(\MyLabel.Type.y(val:10) == \MyLabel.Type.y(val:10))
156310

157311
do {
158312
struct S {
@@ -208,3 +362,48 @@ do {
208362
// CHECK: true
209363
print(StaticExample<MyLabel>().isVisible)
210364
}
365+
366+
do {
367+
@dynamicMemberLookup
368+
struct InstanceDynamicMemberLookup<T> {
369+
var obj: T
370+
371+
subscript<U>(dynamicMember member: KeyPath<T, (Int) -> U>) -> (Int) -> U {
372+
get { obj[keyPath: member] }
373+
}
374+
}
375+
376+
// CHECK: 50
377+
let instanceDynamicLookup = InstanceDynamicMemberLookup(obj: MyLabel())
378+
print(instanceDynamicLookup.x(50))
379+
}
380+
381+
extension MyLabel {
382+
static var defaultInitializer: () -> MyLabel { return MyLabel.init }
383+
static var customInitializer: (String) -> MyLabel { return MyLabel.init(customText:) }
384+
}
385+
386+
do {
387+
@dynamicMemberLookup
388+
struct StaticDynamicMemberLookup<T> {
389+
subscript<U>(dynamicMember keyPath: KeyPath<T.Type, (Int) -> U>) -> (Int) -> U {
390+
return T.self[keyPath: keyPath]
391+
}
392+
subscript<U>(dynamicMember keyPath: KeyPath<T.Type, () -> U>) -> () -> U {
393+
return T.self[keyPath: keyPath]
394+
}
395+
subscript<U>(dynamicMember keyPath: KeyPath<T.Type, (String) -> U>) -> (String) -> U {
396+
return T.self[keyPath: keyPath]
397+
}
398+
}
399+
400+
// CHECK: 60
401+
let staticDynamicLookup = StaticDynamicMemberLookup<MyLabel>()
402+
print(staticDynamicLookup.y(60))
403+
// CHECK: label
404+
let defaultInstance = staticDynamicLookup.defaultInitializer()
405+
print(defaultInstance.text)
406+
// CHECK: Custom Label
407+
let customInstance = staticDynamicLookup.customInitializer("Custom Label")
408+
print(customInstance.text)
409+
}

test/Interpreter/static_keypaths.swift

Lines changed: 23 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
@@ -41,6 +48,10 @@ public let keyPath3FromLibB = \AStruct.Type.property3
4148
public let keyPath4FromLibB = \AStruct.Type.property4
4249
public var keyPath5FromLibB = \AStruct.Type.property1 // WritableKeyPath with public setter
4350
public var keyPath6FromLibB = \Int.Type.zero
51+
public let keyPath7FromLibB = \AStruct.Type.x(val: 10)
52+
public let keyPath8FromLibB = \AStruct.Type.y(val: 10)
53+
public let keyPath9FromLibB = \AStruct.Type.init
54+
public let keyPath10FromLibB = \AStruct.Type.init(val: 2025)
4455

4556
//--- LibC.swift
4657
import LibA
@@ -51,6 +62,9 @@ public let keyPath3FromLibC = \AStruct.Type.property3 // Read-only with private
5162
public let keyPath4FromLibC = \AStruct.Type.property4
5263
public var keyPath5FromLibC = \Int.Type.zero
5364
public var keyPath6FromLibC = \Int.Type.max
65+
public let keyPath7FromLibC = \AStruct.Type.x(val: 10)
66+
public let keyPath8FromLibC = \AStruct.Type.init
67+
public let keyPath9FromLibC = \AStruct.Type.init(val: 2026)
5468

5569
//--- main.swift
5670
import LibB
@@ -73,3 +87,12 @@ print(keyPath5FromLibB == keyPath3FromLibC)
7387
print(keyPath6FromLibB == keyPath5FromLibC)
7488
// Check: false
7589
print(keyPath6FromLibB == keyPath6FromLibC)
90+
91+
// CHECK: true
92+
print(keyPath7FromLibB == keyPath7FromLibC)
93+
// CHECK: false
94+
print(keyPath8FromLibB == keyPath7FromLibC)
95+
// CHECK: true
96+
print(keyPath9FromLibB == keyPath8FromLibC)
97+
// CHECK: true
98+
print(keyPath10FromLibB != keyPath9FromLibC)

0 commit comments

Comments
 (0)