Skip to content

Commit 15c219c

Browse files
committed
[Tests] Add tests.
1 parent 78e7f6a commit 15c219c

File tree

9 files changed

+529
-25
lines changed

9 files changed

+529
-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/Demangle/Inputs/manglings.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,8 @@ $sSUss17FixedWidthIntegerRzrlEyxqd__cSzRd__lufCSu_SiTg5 ---> generic specializat
368368
$s4test7genFuncyyx_q_tr0_lFSi_SbTtt1g5 ---> generic specialization <Swift.Int, Swift.Bool> of test.genFunc<A, B>(A, B) -> ()
369369
$sSD5IndexVy__GD ---> $sSD5IndexVy__GD
370370
$s4test3StrCACycfC ---> {T:$s4test3StrCACycfc} test.Str.__allocating_init() -> test.Str
371+
@$s8keypaths1KV3valACSi_tcfcACmTkmu : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type) -> @out @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <Int, K>)
372+
@$s8keypaths1KVACycfcACmTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type) -> @out K)
371373
$s18keypaths_inlinable13KeypathStructV8computedSSvpACTKq ---> key path getter for keypaths_inlinable.KeypathStruct.computed : Swift.String : keypaths_inlinable.KeypathStruct, serialized
372374
$s18resilient_protocol24ResilientDerivedProtocolPxAA0c4BaseE0Tn --> associated conformance descriptor for resilient_protocol.ResilientDerivedProtocol.A: resilient_protocol.ResilientBaseProtocol
373375
$s3red4testyAA3ResOyxSayq_GAEs5ErrorAAq_sAFHD1__HCg_GADyxq_GsAFR_r0_lF ---> red.test<A, B where B: Swift.Error>(red.Res<A, B>) -> red.Res<A, [B]>

test/Interpreter/keypath.swift

Lines changed: 213 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,98 @@ 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: 7
244+
let kpAdd = \S.add
245+
let resultAdd = S()[keyPath: kpAdd](3, 4)
246+
print(resultAdd)
247+
// CHECK: \S.<computed {{.*}} ((Int) -> Int)>
248+
print(\S.add(this:))
249+
// CHECK: \S.<computed {{.*}} (Int)>
250+
print(\S.add(that: 1))
251+
// CHECK: \S.Type.<computed {{.*}} ((Int) -> Int)>
252+
print(\S.Type.subtract)
253+
// CHECK: \S.Type.<computed {{.*}} (Int)>
254+
print(\S.Type.subtract(1))
255+
// CHECK: \S.<computed {{.*}} (() -> Int)>
256+
print(\S.nonisolatedNextYear)
257+
// CHECK: \S.<computed {{.*}} (Int)>
258+
print(\S.nonisolatedNextYear())
259+
// CHECK: \S.Type.<computed {{.*}} (S)>.<computed {{.*}} (Int)>
260+
print(\S.Type.init(val:2025).nonisolatedNextYear())
261+
// CHECK: 2026
262+
let kpMethodProperty = \S.Type.init(val:2025).nonisolatedNextYear().description
263+
let resultMethodProperty = S.self[keyPath: kpMethodProperty]
264+
print(resultMethodProperty)
265+
// CHECK: \S.Type.<computed {{.*}} (S)>.<computed {{.*}} (Int)>.<computed {{.*}} (Int)>
266+
print(\S.Type.init(val:2025).nonisolatedNextYear().signum())
267+
// // CHECK: \S.<computed {{.*}} (())>
268+
print(\S.consume())
269+
270+
// CHECK: false
271+
print(\S.add(that: 1) == \S.add(this: 1))
272+
// CHECK: false
273+
print(\S.add(that: 1) == \S.add(this: 2))
274+
// CHECK: false
275+
print(\S.Type.init(val: 2024) == \S.Type.init(val: 2025))
276+
// CHECK: false
277+
print(\S.Type.init(val: 2024).nonisolatedNextYear() == \S.Type.init(val: 2025))
278+
// CHECK: true
279+
print(\S.Type.init(val: 2024).add(this: 1) != \S.Type.init(val: 2025))
280+
281+
class E: Hashable {
282+
static func == (lhs: E, rhs: E) -> Bool { return lhs === rhs }
283+
func hash(into hasher: inout Hasher) {
284+
hasher.combine(ObjectIdentifier(self))
285+
}
286+
}
287+
struct BaseType {
288+
func foo(hashableParam e: E) {}
289+
}
290+
let hashableInstance = E()
291+
// CHECK: \BaseType.<computed {{.*}} (())>
292+
print(\BaseType.foo(hashableParam: hashableInstance))
293+
294+
protocol Describable {
295+
func describe() -> String
296+
}
297+
struct C: Describable {
298+
var name: String
299+
func describe() -> String { return "\(name)" }
300+
}
301+
// CHECK: \C.<computed {{.*}} (() -> String)>
302+
print(\C.describe)
303+
304+
// CHECK: false
305+
print(\S.Type.init(val:2025) == \S.Type.init(val:2026))
306+
// CHECK: false
307+
print(\S.Type.init(val:2025).nonisolatedNextYear() == \S.Type.init(val:2026).nonisolatedNextYear())
308+
// CHECK: true
309+
print(\S.Type.init(val:2025).nonisolatedNextYear() == \S.Type.init(val:2025).nonisolatedNextYear())
310+
// CHECK: false
311+
print(\MyLabel.x(val:10) == \MyLabel.x(val:20))
312+
// CHECK: true
313+
print(\MyLabel.Type.y(val:10) == \MyLabel.Type.y(val:10))
156314

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

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)