mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
186 lines
4.6 KiB
Swift
186 lines
4.6 KiB
Swift
//===--- CollectionCasts.swift.gyb ----------------------------*- swift -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// RUN: %empty-directory(%t)
|
|
// RUN: %gyb %s -o %t/CollectionCasts.swift
|
|
// RUN: %line-directive %t/CollectionCasts.swift -- %target-build-swift %t/CollectionCasts.swift -o %t/a.out
|
|
// RUN: %target-codesign %t/a.out && %line-directive %t/CollectionCasts.swift -- %target-run %t/a.out 2>&1
|
|
// REQUIRES: executable_test
|
|
|
|
import StdlibUnittest
|
|
|
|
class Base : Hashable {
|
|
var value: Int
|
|
init(_ value: Int) {
|
|
self.value = value
|
|
}
|
|
func hash(into hasher: inout Hasher) {
|
|
hasher.combine(value)
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
%{
|
|
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 = expectNotNil(source as? ${Collection}<${Key0}>)
|
|
else { return }
|
|
|
|
% else:
|
|
|
|
guard let downcasted = expectNotNil(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 = expectNotNil(upcasted_) else { return }
|
|
% end
|
|
|
|
expectEqual(source.count, upcasted.count)
|
|
|
|
for (k0, v0) in source {
|
|
guard let v1 = expectNotNil(upcasted[k0]) else { continue }
|
|
|
|
guard let dv0 = expectNotNil(
|
|
cast(v0, to: ${DynamicValue}.self)) else { continue }
|
|
|
|
guard let dv1 = expectNotNil(
|
|
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 = expectNotNil(source as? [${Key0}:${Value0}])
|
|
else { return }
|
|
|
|
expectEqual(source.count, downcasted.count)
|
|
|
|
for (k0, v0) in downcasted {
|
|
guard let v1 = expectNotNil(source[k0]) else { continue }
|
|
|
|
guard let dv0 = expectNotNil(
|
|
cast(v0, to: ${DynamicValue}.self)) else { continue }
|
|
|
|
guard let dv1 = expectNotNil(
|
|
cast(v1, to: ${DynamicValue}.self)) else { continue }
|
|
|
|
expectEqual(dv0, dv1)
|
|
}
|
|
}
|
|
|
|
% end
|
|
|
|
% end
|
|
% end
|
|
% end
|
|
% end
|
|
% end
|
|
|
|
|
|
runAllTests()
|
|
|