// RUN: %target-run-simple-swift // // RUN: %target-build-swift -swift-version 5 -O %s -o %t/a.swift5.O.out // RUN: %target-codesign %t/a.swift5.O.out // RUN: %target-run %t/a.swift5.O.out // // RUN: %target-build-swift -swift-version 5 -Onone %s -o %t/a.swift5.Onone.out // RUN: %target-codesign %t/a.swift5.Onone.out // RUN: %target-run %t/a.swift5.Onone.out // // REQUIRES: executable_test import StdlibUnittest let tupleCastTests = TestSuite("Tuple casting") func anyToIntPoint(_ x: Any) -> (x: Int, y: Int) { return x as! (x: Int, y: Int) } func anyToIntPointOpt(_ x: Any) -> (x: Int, y: Int)? { return x as? (x: Int, y: Int) } func anyToInt2(_ x: Any) -> (Int, Int) { return x as! (Int, Int) } func anyToPartlyLabeled(_ x: Any) -> (first: Int, Int, third: Int) { return x as! (first: Int, Int, third: Int) } tupleCastTests.test("Adding/removing labels") { expectEqual("(x: 1, y: 2)", String(describing: anyToIntPoint((x: 1, y: 2)))) expectEqual("(x: 3, y: 4)", String(describing: anyToIntPoint((3, 4)))) expectEqual("(x: 5, y: 6)", String(describing: anyToIntPoint((x: 5, 6)))) expectEqual("(x: 5, y: 6)", String(describing: anyToIntPoint((5, y: 6)))) expectEqual("(1, 2)", String(describing: anyToInt2((1, 2)))) expectEqual("(3, 4)", String(describing: anyToInt2((x: 3, y: 4)))) expectEqual("(5, 6)", String(describing: anyToInt2((x: 5, 6)))) expectEqual("(7, 8)", String(describing: anyToInt2((7, y: 8)))) expectEqual("(first: 1, 2, third: 3)", String(describing: anyToPartlyLabeled((1, 2, 3)))) } tupleCastTests.test("Label checks on casting") { expectTrue((x: 1, y: 2) is (Int, Int)) expectTrue((x: 1, y: 2) is (x: Int, Int)) expectTrue((x: 1, y: 2) is (Int, y: Int)) expectTrue((x: 1, y: 2) is (x: Int, y: Int)) expectFalse((x: 1, y: 2) is (x: Int, z: Int)) expectFalse((x: 1, y: 2) is (a: Int, y: Int)) expectFalse((x: 1, y: 2) is (a: Int, z: Int)) expectFalse((x: 1, y: 2) is (Int, z: Int)) expectFalse((x: 1, y: 2) is (a: Int, Int)) } tupleCastTests.test("Incorrect labels conditional cast") { expectNil(anyToIntPointOpt((x: 1, z: 2))) expectEqual("Optional((x: 1, y: 2))", String(describing: anyToIntPointOpt((x: 1, y: 2)))) } tupleCastTests .test("Incorrect labels forced cast") .crashOutputMatches("Could not cast value of type '(x: Swift.Int, z: Swift.Int)'") .code { expectCrashLater() _ = anyToIntPoint((x: 1, z: 2)) } func castToThree(_ x: Any, _: T.Type, _: U.Type, _: V.Type) -> (t: T, u: U, v: V) { return x as! (t: T, u: U, v: V) } func castToThreeOpt(_ x: Any, _: T.Type, _: U.Type, _: V.Type) -> (t: T, u: U, v: V)? { return x as? (t: T, u: U, v: V) } class LifetimeA { var tracked: LifetimeTracked init(value: Int) { tracked = LifetimeTracked(value) } } class LifetimeB : LifetimeA { } class LifetimeC : LifetimeA { } protocol P { } extension LifetimeA : P { } tupleCastTests.test("Elementwise tuple casts that succeed") { let abc: (P, Any, P) = (LifetimeA(value: 1), LifetimeB(value: 2), LifetimeC(value: 3)) expectEqual( "(t: main.LifetimeA, u: main.LifetimeB, v: main.LifetimeC)", String(describing: castToThree(abc, LifetimeA.self, LifetimeA.self, LifetimeA.self))) expectEqual( "(t: main.LifetimeA, u: main.LifetimeB, v: main.LifetimeC)", String(describing: castToThree((LifetimeA(value: 1), LifetimeB(value: 2), LifetimeC(value: 3)) as (P, Any, P), LifetimeA.self, LifetimeA.self, LifetimeA.self))) } tupleCastTests.test("Elementwise tuple casts that conditionally fail") { let abc: (P, Any, P) = (LifetimeA(value: 1), LifetimeB(value: 2), LifetimeC(value: 3)) expectNil(castToThreeOpt(abc, LifetimeA.self, LifetimeB.self, LifetimeB.self)) expectNil(castToThreeOpt(abc, LifetimeA.self, LifetimeC.self, LifetimeC.self)) expectNil(castToThreeOpt(abc, LifetimeC.self, LifetimeB.self, LifetimeC.self)) } tupleCastTests .test("Elementwise tuple casts that crash (1/3)") .crashOutputMatches("Could not cast value of type 'main.LifetimeA'") .code { let abc: (P, Any, P) = (LifetimeA(value: 1), LifetimeB(value: 2), LifetimeC(value: 3)) expectCrashLater() _ = castToThree(abc, LifetimeC.self, LifetimeB.self, LifetimeC.self) } tupleCastTests .test("Elementwise tuple casts that crash (2/3)") .crashOutputMatches("Could not cast value of type 'main.LifetimeB") .code { let abc: (P, Any, P) = (LifetimeA(value: 1), LifetimeB(value: 2), LifetimeC(value: 3)) expectCrashLater() _ = castToThree(abc, LifetimeA.self, LifetimeC.self, LifetimeC.self) } tupleCastTests .test("Elementwise tuple casts that crash (3/3)") .crashOutputMatches("Could not cast value of type 'main.LifetimeC") .code { let abc: (P, Any, P) = (LifetimeA(value: 1), LifetimeB(value: 2), LifetimeC(value: 3)) expectCrashLater() _ = castToThree(abc, LifetimeA.self, LifetimeB.self, LifetimeB.self) } runAllTests()