Skip to content

Commit be28491

Browse files
committed
[Tests] Add tests.
1 parent 4922283 commit be28491

File tree

6 files changed

+466
-24
lines changed

6 files changed

+466
-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,13 +219,92 @@ 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: \S.Type.<computed {{.*}} (S)>.subscript(_: Int)
240+
print(\S.Type.init()[0])
241+
// CHECK: \S.add
242+
print(\S.add)
243+
// CHECK: \S.<computed {{.*}} ((Int) -> Int)>
244+
print(\S.add(this:))
245+
// CHECK: \S.<computed {{.*}} (Int)>
246+
print(\S.add(that: 1))
247+
// CHECK: \S.Type.<computed {{.*}} ((Int) -> Int)>
248+
print(\S.Type.subtract)
249+
// CHECK: \S.Type.<computed {{.*}} (Int)>
250+
print(\S.Type.subtract(1))
251+
// CHECK: \S.<computed {{.*}} (() -> Int)>
252+
print(\S.nonisolatedNextYear)
253+
// CHECK: \S.<computed {{.*}} (Int)>
254+
print(\S.nonisolatedNextYear())
255+
// CHECK: \S.Type.<computed {{.*}} (S)>.<computed {{.*}} (Int)>
256+
print(\S.Type.init(val:2025).nonisolatedNextYear())
257+
// CHECK: \S.Type.<computed {{.*}} (S)>.<computed {{.*}} (Int)>.description
258+
print(\S.Type.init(val:2025).nonisolatedNextYear().description)
259+
// CHECK: \S.Type.<computed {{.*}} (S)>.<computed {{.*}} (Int)>.<computed {{.*}} (Int)>
260+
print(\S.Type.init(val:2025).nonisolatedNextYear().signum())
261+
// // CHECK: \S.<computed {{.*}} (())>
262+
print(\S.consume())
263+
264+
// CHECK: false
265+
print(\S.add(that: 1) == \S.add(this: 1))
266+
// CHECK: false
267+
print(\S.add(that: 1) == \S.add(this: 2))
268+
// CHECK: false
269+
print(\S.Type.init(val: 2024) == \S.Type.init(val: 2025))
270+
// CHECK: false
271+
print(\S.Type.init(val: 2024).nonisolatedNextYear() == \S.Type.init(val: 2025))
272+
// CHECK: true
273+
print(\S.Type.init(val: 2024).add(this: 1) != \S.Type.init(val: 2025))
274+
275+
class E: Hashable {
276+
static func == (lhs: E, rhs: E) -> Bool { return lhs === rhs }
277+
func hash(into hasher: inout Hasher) {
278+
hasher.combine(ObjectIdentifier(self))
279+
}
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+
protocol Describable {
289+
func describe() -> String
290+
}
291+
struct C: Describable {
292+
var name: String
293+
func describe() -> String { return "\(name)" }
294+
}
295+
// CHECK: \C.<computed {{.*}} (() -> String)>
296+
print(\C.describe)
297+
298+
// CHECK: false
299+
print(\S.Type.init(val:2025) == \S.Type.init(val:2026))
300+
// CHECK: false
301+
print(\S.Type.init(val:2025).nonisolatedNextYear() == \S.Type.init(val:2026).nonisolatedNextYear())
302+
// CHECK: true
303+
print(\S.Type.init(val:2025).nonisolatedNextYear() == \S.Type.init(val:2025).nonisolatedNextYear())
304+
// CHECK: false
305+
print(\MyLabel.x(val:10) == \MyLabel.x(val:20))
306+
// CHECK: true
307+
print(\MyLabel.Type.y(val:10) == \MyLabel.Type.y(val:10))
156308

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

test/Interpreter/static_keypaths.swift

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