// RUN: rm -rf %t && mkdir -p %t // RUN: %target-build-swift %s -Xfrontend -enable-experimental-keypaths -o %t/a.out // RUN: %target-run %t/a.out // REQUIRES: executable_test // REQUIRES: PTRSIZE=64 import StdlibUnittest var keyPath = TestSuite("key paths") final class C { var x: Int var y: LifetimeTracked? var z: T init(x: Int, y: LifetimeTracked?, z: T) { self.x = x self.y = y self.z = z } } struct Point: Equatable { var x: Double var y: Double var trackLifetime = LifetimeTracked(123) init(x: Double, y: Double) { self.x = x self.y = y } static func ==(a: Point, b: Point) -> Bool { return a.x == b.x && a.y == b.y } } struct S: Equatable { var x: Int var y: LifetimeTracked? var z: T var p: Point var c: C static func ==(a: S, b: S) -> Bool { return a.x == b.x && a.y === b.y && a.z == b.z && a.p == b.p && a.c === b.c } } final class ComputedA { var readOnly: ComputedB { fatalError() } var nonmutating: ComputedB { get { fatalError() } set { fatalError() } } var reabstracted: () -> () = {} } struct ComputedB { var readOnly: ComputedA { fatalError() } var mutating: ComputedA { get { fatalError() } set { fatalError() } } var nonmutating: ComputedA { get { fatalError() } nonmutating set { fatalError() } } var reabstracted: () -> () = {} } keyPath.test("key path in-place instantiation") { for _ in 1...2 { let s_x = (#keyPath2(S, .x) as AnyKeyPath) as! WritableKeyPath, Int> let s_y = (#keyPath2(S, .y) as AnyKeyPath) as! WritableKeyPath, LifetimeTracked?> let s_z = (#keyPath2(S, .z) as AnyKeyPath) as! WritableKeyPath, Int> let s_p = (#keyPath2(S, .p) as AnyKeyPath) as! WritableKeyPath, Point> let s_p_x = (#keyPath2(S, .p.x) as AnyKeyPath) as! WritableKeyPath, Double> let s_p_y = (#keyPath2(S, .p.y) as AnyKeyPath) as! WritableKeyPath, Double> let s_c = (#keyPath2(S, .c) as AnyKeyPath) as! WritableKeyPath, C> let s_c_x = (#keyPath2(S, .c.x) as AnyKeyPath) as! ReferenceWritableKeyPath, Int> let c_x = (#keyPath2(C, .x) as AnyKeyPath) as! ReferenceWritableKeyPath, Int> let s_c_x_2 = s_c.appending(path: c_x) expectEqual(s_c_x, s_c_x_2) expectEqual(s_c_x_2, s_c_x) expectEqual(s_c_x.hashValue, s_c_x_2.hashValue) let point_x = (#keyPath2(Point, .x) as AnyKeyPath) as! WritableKeyPath let point_y = (#keyPath2(Point, .y) as AnyKeyPath) as! WritableKeyPath let s_p_x_2 = s_p.appending(path: point_x) let s_p_y_2 = s_p.appending(path: point_y) expectEqual(s_p_x, s_p_x_2) expectEqual(s_p_x_2, s_p_x) expectEqual(s_p_x_2.hashValue, s_p_x.hashValue) expectEqual(s_p_y, s_p_y_2) expectEqual(s_p_y_2, s_p_y) expectEqual(s_p_y_2.hashValue, s_p_y.hashValue) let ca_readOnly = (#keyPath2(ComputedA, .readOnly) as AnyKeyPath) as! KeyPath let ca_nonmutating = (#keyPath2(ComputedA, .nonmutating) as AnyKeyPath) as! ReferenceWritableKeyPath let ca_reabstracted = (#keyPath2(ComputedA, .reabstracted) as AnyKeyPath) as! ReferenceWritableKeyPath ()> let cb_readOnly = (#keyPath2(ComputedB, .readOnly) as AnyKeyPath) as! KeyPath let cb_mutating = (#keyPath2(ComputedB, .mutating) as AnyKeyPath) as! WritableKeyPath let cb_nonmutating = (#keyPath2(ComputedB, .nonmutating) as AnyKeyPath) as! ReferenceWritableKeyPath let cb_reabstracted = (#keyPath2(ComputedB, .reabstracted) as AnyKeyPath) as! WritableKeyPath ()> let ca_readOnly_mutating = (#keyPath2(ComputedA, .readOnly.mutating) as AnyKeyPath) as! KeyPath let cb_mutating_readOnly = (#keyPath2(ComputedB, .mutating.readOnly) as AnyKeyPath) as! KeyPath let ca_readOnly_nonmutating = (#keyPath2(ComputedA, .readOnly.nonmutating) as AnyKeyPath) as! ReferenceWritableKeyPath let cb_readOnly_reabstracted = (#keyPath2(ComputedB, .readOnly.reabstracted) as AnyKeyPath) as! ReferenceWritableKeyPath ()> let ca_readOnly_mutating2 = ca_readOnly.appending(path: cb_mutating) expectEqual(ca_readOnly_mutating, ca_readOnly_mutating2) expectEqual(ca_readOnly_mutating2, ca_readOnly_mutating) expectEqual(ca_readOnly_mutating.hashValue, ca_readOnly_mutating2.hashValue) let cb_mutating_readOnly2 = cb_mutating.appending(path: ca_readOnly) expectEqual(cb_mutating_readOnly, cb_mutating_readOnly2) expectEqual(cb_mutating_readOnly2, cb_mutating_readOnly) expectEqual(cb_mutating_readOnly.hashValue, cb_mutating_readOnly2.hashValue) let ca_readOnly_nonmutating2 = ca_readOnly.appending(path: cb_nonmutating) expectEqual(ca_readOnly_nonmutating, ca_readOnly_nonmutating2) expectEqual(ca_readOnly_nonmutating2, ca_readOnly_nonmutating) expectEqual(ca_readOnly_nonmutating.hashValue, ca_readOnly_nonmutating2.hashValue) let cb_readOnly_reabstracted2 = cb_readOnly.appending(path: ca_reabstracted) expectEqual(cb_readOnly_reabstracted, cb_readOnly_reabstracted2) expectEqual(cb_readOnly_reabstracted2, cb_readOnly_reabstracted) expectEqual(cb_readOnly_reabstracted2.hashValue, cb_readOnly_reabstracted.hashValue) } } keyPath.test("key path generic instantiation") { func testWithGenericParam(_: T.Type) -> ReferenceWritableKeyPath, Int> { for i in 1...2 { let s_x = (#keyPath2(S, .x) as AnyKeyPath) as! WritableKeyPath, Int> let s_y = (#keyPath2(S, .y) as AnyKeyPath) as! WritableKeyPath, LifetimeTracked?> let s_z = (#keyPath2(S, .z) as AnyKeyPath) as! WritableKeyPath, T> let s_p = (#keyPath2(S, .p) as AnyKeyPath) as! WritableKeyPath, Point> let s_p_x = (#keyPath2(S, .p.x) as AnyKeyPath) as! WritableKeyPath, Double> let s_p_y = (#keyPath2(S, .p.y) as AnyKeyPath) as! WritableKeyPath, Double> let s_c = (#keyPath2(S, .c) as AnyKeyPath) as! WritableKeyPath, C> let s_c_x = (#keyPath2(S, .c.x) as AnyKeyPath) as! ReferenceWritableKeyPath, Int> let c_x = (#keyPath2(C, .x) as AnyKeyPath) as! ReferenceWritableKeyPath, Int> let s_c_x_2 = s_c.appending(path: c_x) expectEqual(s_c_x, s_c_x_2) expectEqual(s_c_x_2, s_c_x) expectEqual(s_c_x.hashValue, s_c_x_2.hashValue) let point_x = (#keyPath2(Point, .x) as AnyKeyPath) as! WritableKeyPath let point_y = (#keyPath2(Point, .y) as AnyKeyPath) as! WritableKeyPath let s_p_x_2 = s_p.appending(path: point_x) let s_p_y_2 = s_p.appending(path: point_y) expectEqual(s_p_x, s_p_x_2) expectEqual(s_p_x_2, s_p_x) expectEqual(s_p_x_2.hashValue, s_p_x.hashValue) expectEqual(s_p_y, s_p_y_2) expectEqual(s_p_y_2, s_p_y) expectEqual(s_p_y_2.hashValue, s_p_y.hashValue) if i == 2 { return s_c_x } } fatalError() } let s_c_x_int = testWithGenericParam(Int.self) let s_c_x_int2 = #keyPath2(S, .c.x) expectEqual(s_c_x_int, s_c_x_int2) let s_c_x_string = testWithGenericParam(String.self) let s_c_x_string2 = #keyPath2(S, .c.x) expectEqual(s_c_x_string, s_c_x_string2) let s_c_x_lt = testWithGenericParam(LifetimeTracked.self) let s_c_x_lt2 = #keyPath2(S, .c.x) expectEqual(s_c_x_lt, s_c_x_lt2) } runAllTests()