blob: 7e6266d0d548236d697dec28bf0074a3eed51f02 [file] [log] [blame]
// RUN: %target-swift-frontend -O -Xllvm -sil-disable-pass=FunctionSignatureOpts -emit-sil %s | %FileCheck %s
// We want to check two things here:
// - Correctness
// - That certain "is" checks are eliminated based on static analysis at compile-time
//
// In ideal world, all those testNN functions should be simplified down to a single basic block
// which returns either true or false, i.e. all type checks should folded statically.
// REQUIRES: objc_interop
import Foundation
class ObjCX : NSObject {}
struct CX: _ObjectiveCBridgeable {
func _bridgeToObjectiveC() -> ObjCX {
return ObjCX()
}
static func _forceBridgeFromObjectiveC(_ source: ObjCX, result: inout CX?) {}
static func _conditionallyBridgeFromObjectiveC(_ source: ObjCX, result: inout CX?) -> Bool {
return false
}
static func _unconditionallyBridgeFromObjectiveC(_ source: ObjCX?)
-> CX {
var result: CX?
_forceBridgeFromObjectiveC(source!, result: &result)
return result!
}
}
// Check casts to types which are _ObjectiveCBridgeable
func cast0(_ o: AnyObject) -> Bool {
return o is CX
}
// CHECK-LABEL: sil hidden [noinline] @$s17cast_folding_objc5test0SbyF
// CHECK: bb0
// Check that cast is not eliminated even though cast0 is a conversion
// from a class to struct, because it casts to a struct implementing
// the _BridgedToObjectiveC protocol
// CHECK: checked_cast
// CHECK: return
@inline(never)
func test0() -> Bool {
return cast0(NSNumber(value:1))
}
// Check that this cast does not get eliminated, because
// the compiler does not statically know if this object
// is NSNumber can be converted into Int.
// CHECK-LABEL: sil [noinline] @$s17cast_folding_objc35testMayBeBridgedCastFromObjCtoSwiftySiyXlF
// CHECK: unconditional_checked_cast_addr
// CHECK: return
@inline(never)
public func testMayBeBridgedCastFromObjCtoSwift(_ o: AnyObject) -> Int {
return o as! Int
}
// Check that this cast does not get eliminated, because
// the compiler does not statically know if this object
// is NSString can be converted into String.
// CHECK-LABEL: sil [noinline] @$s17cast_folding_objc41testConditionalBridgedCastFromObjCtoSwiftySSSgyXlF
// CHECK: unconditional_checked_cast_addr
// CHECK: return
@inline(never)
public func testConditionalBridgedCastFromObjCtoSwift(_ o: AnyObject) -> String? {
return o as? String
}
public func castObjCToSwift<T>(_ t: T) -> Int {
return t as! Int
}
// Check that compiler understands that this cast always fails
// CHECK-LABEL: sil [noinline] @$s17cast_folding_objc37testFailingBridgedCastFromObjCtoSwiftySiSo8NSStringCF
// CHECK: builtin "int_trap"
// CHECK-NEXT: unreachable
// CHECK-NEXT: }
@inline(never)
public func testFailingBridgedCastFromObjCtoSwift(_ ns: NSString) -> Int {
return castObjCToSwift(ns)
}
// Check that compiler understands that this cast always fails
// CHECK-LABEL: sil [noinline] @$s17cast_folding_objc37testFailingBridgedCastFromSwiftToObjCySiSSF
// CHECK: builtin "int_trap"
// CHECK-NEXT: unreachable
// CHECK-NEXT: }
@inline(never)
public func testFailingBridgedCastFromSwiftToObjC(_ s: String) -> NSInteger {
return s as! NSInteger
}
@inline(never)
public func testCastNSObjectToAnyClass(_ o: NSObject) -> AnyClass {
return o as! AnyClass
}
@inline(never)
public func testCastNSObjectToClassObject(_ o: NSObject) -> NSObject.Type {
return o as! NSObject.Type
}
@inline(never)
public func testCastNSObjectToAnyType(_ o: NSObject) -> Any.Type {
return o as! Any.Type
}
@inline(never)
public func testCastNSObjectToEveryType<T>(_ o: NSObject) -> T.Type {
return o as! T.Type
}
@inline(never)
public func testCastNSObjectToNonClassType(_ o: NSObject) -> Int.Type {
return o as! Int.Type
}
@inline(never)
public func testCastAnyObjectToAnyClass(_ o: AnyObject) -> AnyClass {
return o as! AnyClass
}
@inline(never)
public func testCastAnyObjectToClassObject(_ o: AnyObject) -> AnyObject.Type {
return o as! AnyObject.Type
}
@inline(never)
public func testCastAnyObjectToAnyType(_ o: AnyObject) -> Any.Type {
return o as! Any.Type
}
@inline(never)
public func testCastAnyObjectToEveryType<T>(_ o: AnyObject) -> T.Type {
return o as! T.Type
}
@inline(never)
public func testCastAnyObjectToNonClassType(_ o: AnyObject) -> Int.Type {
return o as! Int.Type
}
@inline(never)
public func testCastAnyToAny2Class(_ o: Any) -> AnyClass {
return o as! AnyClass
}
@inline(never)
public func testCastAnyToClassObject(_ o: Any) -> AnyObject.Type {
return o as! AnyObject.Type
}
@inline(never)
public func testCastAnyToAny2Type(_ o: Any) -> Any.Type {
return o as! Any.Type
}
@inline(never)
public func testCastAnyToEveryType<T>(_ o: Any) -> T.Type {
return o as! T.Type
}
@inline(never)
public func testCastAnyToNonClassType(_ o: Any) -> Int.Type {
return o as! Int.Type
}
@inline(never)
public func testCastEveryToAnyClass<T>(_ o: T) -> AnyClass {
return o as! AnyClass
}
@inline(never)
public func testCastEveryToClassObject<T>(_ o: T) -> AnyObject.Type {
return o as! AnyObject.Type
}
@inline(never)
public func testCastEveryToAnyType<T>(_ o: T) -> Any.Type {
return o as! Any.Type
}
@inline(never)
public func testCastEveryToEvery2Type<T, U>(_ o: U) -> T.Type {
return o as! T.Type
}
@inline(never)
public func testCastEveryToNonClassType<T>(_ o: T) -> Int.Type {
return o as! Int.Type
}
func cast<U, V>(_ u: U.Type) -> V? {
return u as? V
}
public protocol P {
}
// Any casts from P.Protocol to P.Type should fail.
@inline(never)
public func testCastPProtocolToPType() -> ObjCP.Type? {
return cast(ObjCP.self)
}
@objc
public protocol ObjCP {
}
@inline(never)
public func testCastObjCPProtocolToObjCPType() -> ObjCP.Type? {
return cast(ObjCP.self)
}
@inline(never)
public func testCastProtocolCompositionProtocolToProtocolCompositionType() -> (P & ObjCP).Type? {
return cast((P & ObjCP).self)
}
@inline(never)
public func testCastProtocolCompositionProtocolToProtocolType () -> P.Type? {
return (P & ObjCP).self as? P.Type
}
print("test0=\(test0())")
// CHECK-LABEL: sil [noinline] @{{.*}}testCastNSObjectToEveryType{{.*}}
// CHECK: unconditional_checked_cast_addr
// CHECK-LABEL: sil [noinline] @{{.*}}testCastNSObjectToNonClassType
// CHECK: builtin "int_trap"
// CHECK-LABEL: sil [noinline] @{{.*}}testCastAnyObjectToEveryType{{.*}}
// CHECK: unconditional_checked_cast_addr
// CHECK-LABEL: sil [noinline] @{{.*}}testCastAnyObjectToNonClassType
// CHECK-NOT: builtin "int_trap"
// CHECK-LABEL: sil [noinline] @{{.*}}testCastAnyToAny2Class{{.*}}
// CHECK: unconditional_checked_cast_addr
// CHECK-LABEL: sil [noinline] @{{.*}}testCastAnyToClassObject{{.*}}
// CHECK: unconditional_checked_cast_addr
// CHECK-LABEL: sil [noinline] @{{.*}}testCastAnyToAny2Type{{.*}}
// CHECK: unconditional_checked_cast_addr
// CHECK-LABEL: sil [noinline] @{{.*}}testCastAnyToEveryType{{.*}}
// CHECK: unconditional_checked_cast_addr
// CHECK-LABEL: sil [noinline] @{{.*}}testCastAnyToNonClassType
// CHECK: unconditional_checked_cast_addr
// CHECK-LABEL: sil [noinline] @{{.*}}testCastEveryToAnyClass{{.*}}
// CHECK: unconditional_checked_cast_addr
// CHECK-LABEL: sil [noinline] @{{.*}}testCastEveryToClassObject{{.*}}
// CHECK: unconditional_checked_cast_addr
// CHECK-LABEL: sil [noinline] @{{.*}}testCastEveryToAnyType{{.*}}
// CHECK: unconditional_checked_cast_addr
// CHECK-LABEL: sil [noinline] @{{.*}}testCastEveryToEvery2Type{{.*}}
// CHECK: unconditional_checked_cast_addr
// CHECK-LABEL: sil [noinline] @{{.*}}testCastEveryToNonClassType
// CHECK: unconditional_checked_cast_addr
// CHECK-LABEL: sil [noinline] @{{.*}}testCastPProtocolToPType
// CHECK: %0 = enum $Optional{{.*}}, #Optional.none!enumelt
// CHECK-NEXT: return %0
// CHECK-LABEL: sil [noinline] @{{.*}}testCastObjCPProtocolTo{{.*}}PType
// CHECK: %0 = enum $Optional{{.*}}, #Optional.none!enumelt
// CHECK-NEXT: return %0
// CHECK-LABEL: sil [noinline] @{{.*}}testCastProtocolComposition{{.*}}Type
// CHECK: %0 = enum $Optional{{.*}}, #Optional.none!enumelt
// CHECK-NEXT: return %0
// Check that compiler understands that this cast always succeeds.
// Since it is can be statically proven that NSString is bridgeable to String,
// _forceBridgeFromObjectiveC from String should be invoked instead of
// a more general, but less effective swift_bridgeNonVerbatimFromObjectiveC, which
// also performs conformance checks at runtime.
@inline(never)
public func testBridgedCastFromObjCtoSwift(_ ns: NSString) -> String {
return ns as String
}
// Check that compiler understands that this cast always succeeds
// CHECK-LABEL: sil [noinline] @$s17cast_folding_objc30testBridgedCastFromSwiftToObjCySo8NSStringCSSF
// CHECK-NOT: {{ cast}}
// CHECK: function_ref @$sSS10FoundationE19_bridgeToObjectiveC{{[_0-9a-zA-Z]*}}F
// CHECK: apply
// CHECK: return
@inline(never)
public func testBridgedCastFromSwiftToObjC(_ s: String) -> NSString {
return s as NSString
}
public class MyString: NSString {}
// Check that the cast-optimizer bails out on a conditional downcast to a subclass of a
// bridged ObjC class.
// CHECK-LABEL: sil [noinline] @{{.*}}testConditionalBridgedCastFromSwiftToNSObjectDerivedClass{{.*}}
// CHECK: function_ref @$sSS10FoundationE19_bridgeToObjectiveC{{[_0-9a-zA-Z]*}}F
// CHECK: apply
// CHECK-NOT: apply
// CHECK-NOT: unconditional_checked_cast
// CHECK: checked_cast_br
// CHECK-NOT: apply
// CHECK-NOT: unconditional
// CHECK: return
@inline(never)
public func testConditionalBridgedCastFromSwiftToNSObjectDerivedClass(_ s: String) -> MyString? {
return s as? MyString
}
// Check that the cast-optimizer does not bail out on an unconditional downcast to a subclass of a
// bridged ObjC class.
// CHECK-LABEL: sil [noinline] @{{.*}}testForcedBridgedCastFromSwiftToNSObjectDerivedClass{{.*}}
// CHECK: function_ref @$sSS10FoundationE19_bridgeToObjectiveC{{[_0-9a-zA-Z]*}}F
// CHECK: apply
// CHECK-NOT: apply
// CHECK-NOT: checked_cast_br
// CHECK: unconditional_checked_cast
// CHECK-NOT: apply
// CHECK-NOT: unconditional
// CHECK-NOT: checked_cast
// CHECK: return
@inline(never)
public func testForcedBridgedCastFromSwiftToNSObjectDerivedClass(_ s: String) -> MyString {
return s as! MyString
}