IRGen: Lowering for key paths with indices.

This commit is contained in:
Joe Groff
2017-09-15 09:55:45 -07:00
parent 78d75428d6
commit b7566dacdb
7 changed files with 775 additions and 143 deletions

View File

@@ -1,5 +1,5 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -Xfrontend -enable-sil-ownership -Xfrontend -enable-experimental-keypath-components -o %t/a.out
// RUN: %target-build-swift %s -Xfrontend -enable-sil-ownership -Xfrontend -enable-experimental-keypath-components -g -o %t/a.out
// RUN: %target-run %t/a.out
// REQUIRES: executable_test
@@ -546,41 +546,72 @@ keyPath.test("IUO and key paths") {
expectEqual(kp1.hashValue, kp2.hashValue)
}
struct Subscripts<T: Hashable> {
var value: Int
subscript() -> Int {
get {
return value
}
set {
value = newValue
}
struct SubscriptResult<T: Hashable, U: Hashable> {
var canary = LifetimeTracked(3333)
var left: T
var right: U
init(left: T, right: U) {
self.left = left
self.right = right
}
subscript(left: T) -> Bool {
return self.left == left
}
subscript(right: U) -> Bool {
return self.right == right
}
}
struct Subscripts<T: Hashable> {
var canary = LifetimeTracked(4444)
subscript<U: Hashable>(x: T, y: U) -> SubscriptResult<T, U> {
return SubscriptResult(left: x, right: y)
}
subscript(x: Int, y: Int) -> Int {
return x + y
}
subscript<U: Hashable>(x: T, y: U) -> (T, U) {
return (x, y)
}
}
func fullGenericContext<T: Hashable, U: Hashable>(x: T, y: U) -> KeyPath<Subscripts<T>, (T, U)>) {
struct KeyA: Hashable {
var canary = LifetimeTracked(1111)
var value: String
init(value: String) { self.value = value }
static func ==(a: KeyA, b: KeyA) -> Bool { return a.value == b.value }
var hashValue: Int { return value.hashValue }
}
struct KeyB: Hashable {
var canary = LifetimeTracked(2222)
var value: Int
init(value: Int) { self.value = value }
static func ==(a: KeyB, b: KeyB) -> Bool { return a.value == b.value }
var hashValue: Int { return value.hashValue }
}
func fullGenericContext<T: Hashable, U: Hashable>(x: T, y: U) -> KeyPath<Subscripts<T>, SubscriptResult<T, U>> {
return \Subscripts<T>.[x, y]
}
func halfGenericContext<U: Hashable>(x: String, y: U) -> KeyPath<Subscripts<String>, (String, U)> {
return \Subscripts<String>.[x, y]
func halfGenericContext<U: Hashable>(x: KeyA, y: U) -> KeyPath<Subscripts<KeyA>, SubscriptResult<KeyA, U>> {
return \Subscripts<KeyA>.[x, y]
}
func nonGenericContext(x: String, y: Int) -> KeyPath<Subscripts<String>, (String, Int)> {
return \Subscripts<String>.[x, y]
func nonGenericContext(x: KeyA, y: KeyB) -> KeyPath<Subscripts<KeyA>, SubscriptResult<KeyA, KeyB>> {
return \Subscripts<KeyA>.[x, y]
}
keyPath.test("subscripts") {
let a = fullGenericContext("hey", 1738)
let b = halfGenericContext("hey", 1738)
let c = nonGenericContext("hey", 1738)
let a = fullGenericContext(x: KeyA(value: "hey"), y: KeyB(value: 1738))
let b = halfGenericContext(x: KeyA(value: "hey"), y: KeyB(value: 1738))
let c = nonGenericContext(x: KeyA(value: "hey"), y: KeyB(value: 1738))
expectEqual(a, b)
expectEqual(a, c)
@@ -594,8 +625,46 @@ keyPath.test("subscripts") {
expectEqual(b.hashValue, c.hashValue)
expectEqual(c.hashValue, a.hashValue)
expectEqual(c.hashValue, b.hashValue)
}
let base = Subscripts<KeyA>()
let kp2 = \SubscriptResult<KeyA, KeyB>.[KeyA(value: "hey")]
for kp in [a, b, c] {
let projected = base[keyPath: kp]
expectEqual(projected.left.value, "hey")
expectEqual(projected.right.value, 1738)
expectEqual(projected[keyPath: kp2], true)
let kp12 =
\Subscripts<KeyA>.[KeyA(value: "hey"), KeyB(value: 1738)][KeyA(value: "hey")]
let kp12a = kp.appending(path: kp2)
expectEqual(kp12, kp12a)
expectEqual(kp12a, kp12)
expectEqual(kp12.hashValue, kp12a.hashValue)
}
let ints = \Subscripts<KeyA>.[17, 38]
let ints2 = \Subscripts<KeyA>.[17, 38]
let ints3 = \Subscripts<KeyA>.[38, 17]
expectEqual(base[keyPath: ints], 17 + 38)
expectEqual(ints, ints2)
expectEqual(ints2, ints)
expectNotEqual(ints, ints3)
expectNotEqual(ints2, ints3)
expectNotEqual(ints3, ints)
expectNotEqual(ints3, ints2)
expectEqual(ints.hashValue, ints2.hashValue)
let ints_be = ints.appending(path: \Int.bigEndian)
expectEqual(base[keyPath: ints_be], (17 + 38).bigEndian)
}
runAllTests()