| //===--- CollectionCasts.swift.gyb ----------------------------*- swift -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See http://swift.org/LICENSE.txt for license information |
| // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| // RUN: rm -rf %t |
| // RUN: mkdir -p %t |
| // RUN: %gyb %s -o %t/CollectionCasts.swift |
| // RUN: %line-directive %t/CollectionCasts.swift -- %target-build-swift -Xfrontend -enable-experimental-collection-casts %t/CollectionCasts.swift -o %t/a.out |
| // RUN: %line-directive %t/CollectionCasts.swift -- %target-run %t/a.out 2>&1 |
| // REQUIRES: executable_test |
| |
| import StdlibUnittest |
| |
| class Base : Hashable { |
| init(_ value: Int) { |
| self.value = value |
| } |
| var value: Int |
| var hashValue : Int { |
| return value.hashValue |
| } |
| } |
| |
| func == (lhs: Base, rhs: Base) -> Bool { |
| return lhs.value == rhs.value |
| } |
| |
| class Derived : Base {} |
| |
| protocol AnyFoo { |
| init(_ value: Int) |
| } |
| extension Int : AnyFoo { } |
| |
| var tests = TestSuite("CollectionCasts") |
| |
| // A wrapper for an as? cast that suppresses warnings when the cast always |
| // succeeds. |
| func cast<T, U>(_ x: T, to result: U.Type) -> U? { |
| return x as? U |
| } |
| |
| %{ |
| from gyb_stdlib_unittest_support import TRACE, stackTrace, trace |
| classKeys = ('Derived', 'Base') |
| classValues = classKeys + ('AnyObject', 'Any') |
| nonClassKeys = ('Int',) |
| nonClassValues = ('Int', 'AnyFoo', 'Any') |
| }% |
| |
| % for keys, values in [ (classKeys, classValues), (nonClassKeys, nonClassValues) ]: |
| |
| % for ki0, Key0 in enumerate(keys): |
| % DynamicKey = keys[0] if Key0.startswith('Any') else Key0 |
| % for Key1 in keys[ki0:]: |
| % for Collection in 'Array', 'Set': |
| |
| tests.test("${Collection}/Up/${Key0}=>${Key1}") { |
| |
| let source : ${Collection} = [ |
| ${DynamicKey}(42) as ${Key0}, |
| ${DynamicKey}(17) as ${Key0}] |
| |
| let upcasted = source as ${Collection}<${Key1}> |
| |
| expectEqual(source.count, upcasted.count) |
| for x in source { |
| expectTrue(upcasted.contains(x)) |
| } |
| } |
| |
| % if Key1 != Key0: |
| % for method in 'Direct', 'Indirect': |
| tests.test("${Collection}/Down/${method}/${Key1}=>${Key0}") { |
| |
| let source : ${Collection} = [ |
| ${DynamicKey}(42) as ${Key1}, |
| ${DynamicKey}(17) as ${Key1}] |
| |
| % if method == 'Direct': |
| |
| guard let downcasted = expectNotEmpty(source as? ${Collection}<${Key0}>) |
| else { return } |
| |
| % else: |
| |
| guard let downcasted = expectNotEmpty(cast(source, to: ${Collection}<${Key0}>.self)) |
| else { return } |
| |
| % end |
| |
| expectEqual(source.count, downcasted.count) |
| for x in downcasted { |
| expectTrue(source.contains(x)) |
| } |
| } |
| % end |
| % end |
| % end |
| |
| |
| % for vi0, Value0 in enumerate(values): |
| % DynamicValue = values[0] if Value0.startswith('Any') else Value0 |
| % for Value1 in values[vi0:]: |
| |
| % for method in 'Direct', 'Indirect': |
| |
| tests.test( |
| "Dictionary/Up/${method}/[${Key0}:${Value0}]=>[${Key1}:${Value1}]") { |
| |
| // Check that the cast type-checks |
| let source = [ |
| ${DynamicKey}(42) as ${Key0} : ${DynamicValue}(42) as ${Value0}, |
| ${DynamicKey}(17) as ${Key0} : ${DynamicValue}(17) as ${Value0}] |
| |
| |
| % if method == 'Direct': |
| let upcasted = source as [${Key1}:${Value1}] |
| % else: |
| let upcasted_ = source as Any as? [${Key1}:${Value1}] |
| |
| guard let upcasted = expectNotEmpty(upcasted_) else { return } |
| % end |
| |
| expectEqual(source.count, upcasted.count) |
| |
| for (k0, v0) in source { |
| guard let v1 = expectNotEmpty(upcasted[k0]) else { continue } |
| |
| guard let dv0 = expectNotEmpty( |
| cast(v0, to: ${DynamicValue}.self)) else { continue } |
| |
| guard let dv1 = expectNotEmpty( |
| cast(v1, to: ${DynamicValue}.self)) else { continue } |
| |
| expectEqual(dv0, dv1) |
| } |
| } |
| |
| % end |
| |
| % if Key1 != Key0 or Value1 != Value0: |
| |
| tests.test( |
| "Dictionary/Down/[${Key1}:${Value1}]=>[${Key0}:${Value0}]") { |
| |
| // Check that the cast type-checks |
| let source = [ |
| ${DynamicKey}(42) as ${Key1} : ${DynamicValue}(42) as ${Value1}, |
| ${DynamicKey}(17) as ${Key1} : ${DynamicValue}(17) as ${Value1}] |
| |
| guard let downcasted = expectNotEmpty(source as? [${Key0}:${Value0}]) |
| else { return } |
| |
| expectEqual(source.count, downcasted.count) |
| |
| for (k0, v0) in downcasted { |
| guard let v1 = expectNotEmpty(source[k0]) else { continue } |
| |
| guard let dv0 = expectNotEmpty( |
| cast(v0, to: ${DynamicValue}.self)) else { continue } |
| |
| guard let dv1 = expectNotEmpty( |
| cast(v1, to: ${DynamicValue}.self)) else { continue } |
| |
| expectEqual(dv0, dv1) |
| } |
| } |
| |
| % end |
| |
| % end |
| % end |
| % end |
| % end |
| % end |
| |
| |
| runAllTests() |
| |