// RUN: rm -rf %t // RUN: mkdir -p %t // RUN: %S/../../utils/gyb %s -o %t/ArrayTraps.swift // RUN: %S/../../utils/line-directive %t/ArrayTraps.swift -- %target-build-swift %t/ArrayTraps.swift -o %t/a.out_Debug // RUN: %S/../../utils/line-directive %t/ArrayTraps.swift -- %target-build-swift %t/ArrayTraps.swift -o %t/a.out_Release -O // // RUN: %S/../../utils/line-directive %t/ArrayTraps.swift -- %target-run %t/a.out_Debug // RUN: %S/../../utils/line-directive %t/ArrayTraps.swift -- %target-run %t/a.out_Release // REQUIRES: executable_test // REQUIRES: objc_interop import StdlibUnittest // Also import modules which are used by StdlibUnittest internally. This // workaround is needed to link all required libraries in case we compile // StdlibUnittest with -sil-serialize-all. import SwiftPrivate #if _runtime(_ObjC) import ObjectiveC #endif import Foundation var ArrayTraps = TestSuite("ArrayTraps") class Base { } class Derived : Base { } class Derived2 : Derived { } ArrayTraps.test("downcast1") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { let ba: [Base] = [ Derived(), Base() ] let da = ba as! [Derived] let d0 = da[0] expectCrashLater() da[1] } ArrayTraps.test("downcast2") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { let a: [AnyObject] = [ "String", 1 ] let sa = a as! [NSString] let s0 = sa[0] expectCrashLater() sa[1] } ArrayTraps.test("downcast3") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { let ba: [Base] = [ Derived2(), Derived(), Base() ] let d2a = ba as! [Derived2] let d2a0 = d2a[0] let d1a = d2a as [Derived] let d1a0 = d1a[0] let d1a1 = d1a[1] expectCrashLater() d1a[2] } @objc protocol ObjCProto { } class ObjCBase : NSObject, ObjCProto { } class ObjCDerived : ObjCBase { } ArrayTraps.test("downcast4") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { let ba: [ObjCProto] = [ ObjCDerived(), ObjCBase() ] let da = ba as! [ObjCDerived] let d0 = da[0] expectCrashLater() da[1] } ArrayTraps.test("bounds_with_downcast") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .crashOutputMatches(_isDebugAssertConfiguration() ? "fatal error: Index out of range" : "") .code { let ba: [Base] = [ Derived(), Base() ] let da = ba as! [Derived] expectCrashLater() let x = da[2] } var ArraySemanticOptzns = TestSuite("ArraySemanticOptzns") class BaseClass { } class ElementClass : BaseClass { var val: String init(_ x: String) { val = x } } class ViolateInoutSafetySwitchToObjcBuffer { final var anArray: [ElementClass] = [] let nsArray = NSArray( objects: ElementClass("a"), ElementClass("b"), ElementClass("c")) @inline(never) func accessArrayViaInoutViolation() { anArray = _convertNSArrayToArray(nsArray) } @inline(never) func runLoop(A: inout [ElementClass]) { // Simulate what happens if we hoist array properties out of a loop and the // loop calls a function that violates inout safety and overrides the array. let isNativeTypeChecked = A._hoistableIsNativeTypeChecked() for i in 0..