Skip to content

Commit a34bdb4

Browse files
committed
[Tests] Add tests.
1 parent 6e43af2 commit a34bdb4

File tree

6 files changed

+469
-24
lines changed

6 files changed

+469
-24
lines changed

test/Constraints/keypath.swift

+4-2
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

+207-10
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,90 @@ 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+
}
279+
struct BaseType {
280+
func foo(hashableParam e: E) {}
281+
}
282+
let hashableInstance = E()
283+
// CHECK: \BaseType.<computed {{.*}} (())>
284+
print(\BaseType.foo(hashableParam: hashableInstance))
285+
286+
protocol Describable {
287+
func describe() -> String
288+
}
289+
struct C: Describable {
290+
var name: String
291+
func describe() -> String { return "\(name)" }
292+
}
293+
// CHECK: \C.<computed {{.*}} (() -> String)>
294+
print(\C.describe)
295+
296+
// CHECK: false
297+
print(\S.Type.init(val:2025) == \S.Type.init(val:2026))
298+
// CHECK: false
299+
print(\S.Type.init(val:2025).nonisolatedNextYear() == \S.Type.init(val:2026).nonisolatedNextYear())
300+
// CHECK: true
301+
print(\S.Type.init(val:2025).nonisolatedNextYear() == \S.Type.init(val:2025).nonisolatedNextYear())
302+
// CHECK: false
303+
print(\MyLabel.x(val:10) == \MyLabel.x(val:20))
304+
// CHECK: true
305+
print(\MyLabel.Type.y(val:10) == \MyLabel.Type.y(val:10))
154306

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

test/Interpreter/static_keypaths.swift

+26
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)