Files
swift-mirror/test/stdlib/KeyPathMultiModule.swift
Joe Groff 9c9fa8545a IRGen: Use base-relative offsets to identify methods in fragile subclasses of resilient bases in key paths.
The resilient methods will all be keyed by their dispatch thunks, so for methods of local subclasses, we can use the offsets relative to the dynamic base as identifiers without having to adjust for that dynamic base.
2018-07-27 13:15:49 -07:00

213 lines
9.8 KiB
Swift

// -- Test with resilience enabled
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -force-single-frontend-invocation -Xfrontend -enable-key-path-resilience -Xfrontend -enable-resilience -module-name KeyPathMultiModule_b -c -o %t/KeyPathMultiModule_b.o -emit-module-path %t/KeyPathMultiModule_b.swiftmodule -parse-as-library %S/Inputs/KeyPathMultiModule_b.swift
// RUN: %target-build-swift -g -Xfrontend -enable-key-path-resilience %t/KeyPathMultiModule_b.o -I %t %s -o %t/a.out.resilient
// RUN: %target-run %t/a.out.resilient
// -- Test again with resilience disabled, which changes the circumstances under
// which we emit and use property descriptors
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -force-single-frontend-invocation -Xfrontend -enable-key-path-resilience -module-name KeyPathMultiModule_b -c -o %t/KeyPathMultiModule_b.o -emit-module-path %t/KeyPathMultiModule_b.swiftmodule -parse-as-library %S/Inputs/KeyPathMultiModule_b.swift
// RUN: %target-build-swift -Xfrontend -enable-key-path-resilience %t/KeyPathMultiModule_b.o -I %t %s -o %t/a.out.fragile
// RUN: %target-run %t/a.out.fragile
import KeyPathMultiModule_b
import StdlibUnittest
var keyPathMultiModule = TestSuite("key paths across multiple modules")
func expectEqualWithHashes<T: Hashable>(_ x: T, _ y: T,
file: String = #file,
line: UInt = #line) {
expectEqual(x, y, file: file, line: line)
expectEqual(x.hashValue, y.hashValue, file: file, line: line)
}
class LocalSub: ResilientSub {
override var virtual: String {
get {
return "bas"
}
set {
}
}
final var storedD: String = "zim"
final var storedE: String = "zang"
var localSubA: String {
get { return "zung" }
}
var localSubB: String {
get { return "zipiti" }
}
}
keyPathMultiModule.test("identity across multiple modules") {
// Do this twice, to ensure that fully constant key paths remain stable
// after one-time instantiation of the object
for _ in 1...2 {
expectEqualWithHashes(A_x_keypath(), \A.x)
expectEqualWithHashes(A_y_keypath(), \A.y)
expectEqualWithHashes(A_z_keypath(), \A.z)
expectEqualWithHashes(A_subscript_withGeneric_keypath(index: 0), \A.[withGeneric: 0])
expectEqualWithHashes(A_subscript_withGeneric_keypath(index: "butt"),
\A.[withGeneric: "butt"])
expectEqualWithHashes(A_subscript_withGeneric_butt_keypath(),
\A.[withGeneric: "pomeranian's big butt"])
expectEqualWithHashes(A_subscript_withGenericSettable_keypath(index: 0),
\A.[withGenericSettable: 0])
expectEqualWithHashes(A_subscript_withGenericSettable_keypath(index: "butt"),
\A.[withGenericSettable: "butt"])
expectEqualWithHashes(A_subscript_withGenericPrivateSet_keypath(index: 0),
\A.[withGenericPrivateSet: 0])
expectEqualWithHashes(A_subscript_withGenericPrivateSet_keypath(index: "butt"),
\A.[withGenericPrivateSet: "butt"])
do {
let lifetimeTracker = LifetimeTracked(679)
expectEqualWithHashes(A_subscript_withGeneric_keypath(index: lifetimeTracker),
\A.[withGeneric: lifetimeTracker])
expectEqualWithHashes(A_subscript_withGenericSettable_keypath(index: lifetimeTracker),
\A.[withGenericSettable: lifetimeTracker])
expectEqualWithHashes(A_subscript_withGenericPrivateSet_keypath(index: lifetimeTracker),
\A.[withGenericPrivateSet: lifetimeTracker])
expectEqualWithHashes(\A.[withGeneric: lifetimeTracker].appendTest,
(\A.[withGeneric: lifetimeTracker])
.appending(path: \LifetimeTracked.appendTest))
expectEqualWithHashes(\A.[withGenericSettable: lifetimeTracker].appendTest,
(\A.[withGenericSettable: lifetimeTracker])
.appending(path: \LifetimeTracked.appendTest))
expectEqualWithHashes(\A.[withGenericPrivateSet: lifetimeTracker].appendTest,
(\A.[withGenericPrivateSet: lifetimeTracker])
.appending(path: \LifetimeTracked.appendTest))
}
expectEqualWithHashes(B_x_keypath(Double.self), \B<Double>.x)
expectEqualWithHashes(B_Int_x_keypath(), \B<Int>.x)
expectEqualWithHashes(B_y_keypath(Double.self), \B<Double>.y)
expectEqualWithHashes(B_Int_y_keypath(), \B<Int>.y)
expectEqualWithHashes(B_z_keypath(Double.self), \B<Double>.z)
expectEqualWithHashes(B_Int_z_keypath(), \B<Int>.z)
expectEqualWithHashes(B_subscript_withInt_keypath(Double.self, index: 1738),
\B<Double>.[withInt: 1738])
expectEqualWithHashes(B_subscript_withInt_keypath(Double.self, index: 679),
\B<Double>.[withInt: 679])
expectEqualWithHashes(B_Double_subscript_withInt_0_keypath(),
\B<Double>.[withInt: 0])
expectEqualWithHashes(B_subscript_withGeneric_keypath(Double.self, index: "buttt"),
\B<Double>.[withGeneric: "buttt"])
expectEqualWithHashes(B_Double_subscript_withGeneric_butt_keypath(),
\B<Double>.[withGeneric: "Never is the universal butt type"])
expectEqualWithHashes(A_storedA_keypath(), \A.storedA)
expectEqualWithHashes(A_storedA_storedB_keypath(), \A.storedA.storedB)
expectEqualWithHashes(A_storedB_keypath(), \A.storedB)
expectEqualWithHashes(B_storedA_keypath(Double.self), \B<Double>.storedA)
expectEqualWithHashes(B_storedB_keypath(Double.self), \B<Double>.storedB)
expectEqualWithHashes(B_Int_storedA_keypath(), \B<Int>.storedA)
expectEqualWithHashes(B_Int_storedB_keypath(), \B<Int>.storedB)
func testInGenericContext<X, Y: Hashable, Z>(x: X, y: Y,
appending: KeyPath<Y, Z>) {
expectEqualWithHashes(A_subscript_withGeneric_keypath(index: y),
\A.[withGeneric: y])
expectEqualWithHashes(A_subscript_withGenericSettable_keypath(index: y),
\A.[withGenericSettable: y])
expectEqualWithHashes(A_subscript_withGenericPrivateSet_keypath(index: y),
\A.[withGenericPrivateSet: y])
_ = (\A.[withGeneric: y]).appending(path: appending)
_ = (\A.[withGenericSettable: y]).appending(path: appending)
_ = (\A.[withGenericPrivateSet: y]).appending(path: appending)
expectEqualWithHashes(B_x_keypath(X.self), \B<X>.x)
expectEqualWithHashes(B_y_keypath(X.self), \B<X>.y)
expectEqualWithHashes(B_z_keypath(X.self), \B<X>.z)
expectEqualWithHashes(B_subscript_withInt_keypath(X.self, index: 0),
\B<X>.[withInt: 0])
expectEqualWithHashes(B_subscript_withGeneric_keypath(X.self, index: y),
\B<X>.[withGeneric: y])
expectEqualWithHashes(B_subscript_withGenericSettable_keypath(X.self, index: y),
\B<X>.[withGenericSettable: y])
expectEqualWithHashes(B_subscript_withGenericPrivateSet_keypath(X.self, index: y),
\B<X>.[withGenericPrivateSet: y])
_ = (\B<X>.[withGeneric: y]).appending(path: appending)
_ = (\B<X>.[withGenericSettable: y]).appending(path: appending)
_ = (\B<X>.[withGenericPrivateSet: y]).appending(path: appending)
expectEqualWithHashes(B_storedA_keypath(X.self), \B<X>.storedA)
expectEqualWithHashes(B_storedB_keypath(X.self), \B<X>.storedB)
}
testInGenericContext(x: 0.0, y: 42, appending: \Int.appendTest)
testInGenericContext(x: "pomeranian", y: "big butt",
appending: \String.appendTest)
testInGenericContext(x: LifetimeTracked(17), y: LifetimeTracked(38),
appending: \LifetimeTracked.appendTest)
expectEqualWithHashes(ResilientRoot_storedA_keypath(),
\ResilientRoot.storedA)
expectEqualWithHashes(ResilientRoot_storedB_keypath(),
\ResilientRoot.storedB)
expectEqualWithHashes(ResilientRoot_virtual_keypath(),
\ResilientRoot.virtual)
expectEqualWithHashes(ResilientRoot_virtualRO_keypath(),
\ResilientRoot.virtualRO)
expectEqualWithHashes(ResilientRoot_final_keypath(),
\ResilientRoot.final)
expectEqualWithHashes(ResilientSub_storedA_keypath(),
\ResilientSub.storedA)
expectEqualWithHashes(ResilientSub_storedB_keypath(),
\ResilientSub.storedB)
expectEqualWithHashes(ResilientSub_storedC_keypath(),
\ResilientSub.storedC)
expectEqualWithHashes(ResilientSub_virtual_keypath(),
\ResilientSub.virtual)
expectEqualWithHashes(ResilientSub_virtualRO_keypath(),
\ResilientSub.virtualRO)
expectEqualWithHashes(ResilientSub_final_keypath(),
\ResilientSub.final)
expectEqualWithHashes(ResilientSub_sub_keypath(),
\ResilientSub.sub)
expectEqualWithHashes(ResilientSub_subRO_keypath(),
\ResilientSub.subRO)
// Ensure that we can instantiate key paths on a local subclass of a
// resilient class, and that they have distinct values.
let kps: [PartialKeyPath<LocalSub>] = [
\LocalSub.storedA,
\LocalSub.storedB,
\LocalSub.storedC,
\LocalSub.storedD,
\LocalSub.storedE,
\LocalSub.virtual,
\LocalSub.sub,
\LocalSub.localSubA,
\LocalSub.localSubB,
]
for i in kps.indices {
for j in kps.indices {
if i == j { continue }
expectNotEqual(kps[i], kps[j])
}
}
func testInGenericContext2<W: ResilientSubProto>(_: W.Type) {
expectEqualWithHashes(ResilientRootProto_root_keypath(W.self),
\W.root)
expectEqualWithHashes(ResilientSubProto_sub_keypath(W.self),
\W.sub)
}
testInGenericContext2(Int.self)
}
}
runAllTests()