mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
158 lines
5.2 KiB
Swift
158 lines
5.2 KiB
Swift
// RUN: %empty-directory(%t)
|
|
// RUN: cp -R %S/Inputs/FakeUnavailableObjCFramework.framework %t
|
|
// RUN: %target-clang -dynamiclib %S/Inputs/FakeUnavailableObjCFramework.m -fmodules -F %t -framework Foundation -o %t/FakeUnavailableObjCFramework.framework/FakeUnavailableObjCFramework
|
|
|
|
// RUN: %target-build-swift -F %t %s -o %t/UseWeaklinkedUnavailableObjCFramework
|
|
// RUN: %target-build-swift -O -F %t %s -o %t/UseWeaklinkedUnavailableObjCFramework.opt
|
|
|
|
// These tests emulate deploying back to an older OS where newer APIs are not
|
|
// available by linking to an Objective-C framework where APIs have been
|
|
// annotated to only be available in the far future (version 1066.0 of all
|
|
// platforms) and then moving the framework aside so that it can't be found
|
|
// at run time.
|
|
// RUN: mv %t/FakeUnavailableObjCFramework.framework %t/FakeUnavailableObjCFramework-MovedAside.framework
|
|
|
|
// RUN: %target-run %t/UseWeaklinkedUnavailableObjCFramework | %FileCheck %s
|
|
// RUN: %target-run %t/UseWeaklinkedUnavailableObjCFramework.opt | %FileCheck %s
|
|
|
|
// REQUIRES: objc_interop
|
|
// REQUIRES: executable_test
|
|
|
|
import StdlibUnittest
|
|
|
|
|
|
import FakeUnavailableObjCFramework
|
|
import Foundation
|
|
|
|
// CHECK: Running
|
|
print("Running...")
|
|
|
|
func useUnavailableObjCGlobal() {
|
|
if #available(OSX 1066.0, iOS 1066.0, watchOS 1066.0, tvOS 1066.0, *) {
|
|
let g = UnavailableObjCGlobalVariable
|
|
_blackHole(g)
|
|
}
|
|
}
|
|
|
|
useUnavailableObjCGlobal()
|
|
|
|
@objc
|
|
class ClassConformingToUnavailableObjCProtocol : NSObject, UnavailableObjCProtocol {
|
|
func someMethod() {
|
|
print("Executed ClassConformingToUnavailableObjCProtocol.someMethod()")
|
|
}
|
|
}
|
|
|
|
func useClassConformingToUnavailableObjCProtocol() {
|
|
let o = ClassConformingToUnavailableObjCProtocol()
|
|
o.someMethod()
|
|
|
|
if #available(OSX 1066.0, iOS 1066.0, watchOS 1066.0, tvOS 1066.0, *) {
|
|
let oAsUP: UnavailableObjCProtocol = o as UnavailableObjCProtocol
|
|
oAsUP.someMethod()
|
|
}
|
|
}
|
|
|
|
// CHECK-NEXT: Executed ClassConformingToUnavailableObjCProtocol.someMethod()
|
|
useClassConformingToUnavailableObjCProtocol()
|
|
|
|
@objc
|
|
class ClassThatWillBeExtendedToConformToUnavailableObjCProtocol : NSObject {
|
|
}
|
|
|
|
extension ClassThatWillBeExtendedToConformToUnavailableObjCProtocol : UnavailableObjCProtocol {
|
|
func someMethod() {
|
|
print("Executed ClassThatWillBeExtendedToConformToUnavailableObjCProtocol.someMethod()")
|
|
}
|
|
}
|
|
|
|
func useClassThatWillBeExtendedToConformToUnavailableObjCProtocol() {
|
|
let o = ClassThatWillBeExtendedToConformToUnavailableObjCProtocol()
|
|
o.someMethod()
|
|
|
|
if #available(OSX 1066.0, iOS 1066.0, watchOS 1066.0, tvOS 1066.0, *) {
|
|
let oAsUP: UnavailableObjCProtocol = o as UnavailableObjCProtocol
|
|
oAsUP.someMethod()
|
|
}
|
|
}
|
|
|
|
// CHECK-NEXT: Executed ClassThatWillBeExtendedToConformToUnavailableObjCProtocol.someMethod()
|
|
useClassThatWillBeExtendedToConformToUnavailableObjCProtocol()
|
|
|
|
// We need to gracefully handle ObjC protocols missing availability annotations
|
|
// because it is quite common in frameworks. (Historically, for Objective-C,
|
|
// missing availability annotations on protocols has not been problematic
|
|
// because Objective-C protocol metadata is compiled into any code that
|
|
// references it -- it is not weakly linked.)
|
|
|
|
@objc
|
|
class ClassConformingToUnannotatedUnavailableObjCProtocol : NSObject, UnannotatedUnavailableObjCProtocol {
|
|
func someMethod() {
|
|
print("Executed ClassConformingToUnannotatedUnavailableObjCProtocol.someMethod()")
|
|
}
|
|
}
|
|
|
|
func useClassConformingToUnannotatedUnavailableObjCProtocol() {
|
|
let o = ClassConformingToUnannotatedUnavailableObjCProtocol()
|
|
o.someMethod()
|
|
|
|
let oAsUP: UnannotatedUnavailableObjCProtocol = (o as AnyObject) as! UnannotatedUnavailableObjCProtocol
|
|
oAsUP.someMethod()
|
|
}
|
|
|
|
// CHECK-NEXT: Executed ClassConformingToUnannotatedUnavailableObjCProtocol.someMethod()
|
|
// CHECK-NEXT: Executed ClassConformingToUnannotatedUnavailableObjCProtocol.someMethod()
|
|
useClassConformingToUnannotatedUnavailableObjCProtocol()
|
|
|
|
func printClassMetadataViaGeneric<T>() -> T {
|
|
print("\(T.self)")
|
|
fatalError("This should never be called")
|
|
}
|
|
|
|
func useUnavailableObjCClass() {
|
|
if #available(OSX 1066.0, iOS 1066.0, watchOS 1066.0, tvOS 1066.0, *) {
|
|
let o = UnavailableObjCClass()
|
|
o.someMethod()
|
|
}
|
|
|
|
for i in 0 ..< getInt(5) {
|
|
if #available(OSX 1066.0, iOS 1066.0, watchOS 1066.0, tvOS 1066.0, *) {
|
|
let o: UnavailableObjCClass = printClassMetadataViaGeneric()
|
|
_blackHole(o)
|
|
}
|
|
}
|
|
|
|
class SomeClass { }
|
|
let someObject: AnyObject = _opaqueIdentity(SomeClass() as AnyObject)
|
|
|
|
for i in 0 ..< getInt(5) {
|
|
if #available(OSX 1066.0, iOS 1066.0, watchOS 1066.0, tvOS 1066.0, *) {
|
|
let isUnavailable = someObject is UnavailableObjCClass
|
|
_blackHole(isUnavailable)
|
|
}
|
|
}
|
|
|
|
for i in 0 ..< getInt(5) {
|
|
if #available(OSX 1066.0, iOS 1066.0, watchOS 1066.0, tvOS 1066.0, *) {
|
|
let asUnavailable = someObject as? UnavailableObjCClass
|
|
_blackHole(asUnavailable)
|
|
}
|
|
}
|
|
}
|
|
|
|
@available(OSX 1066.0, iOS 1066.0, watchOS 1066.0, tvOS 1066.0, *)
|
|
func wrapUnavailableFunction() {
|
|
someFunction()
|
|
}
|
|
|
|
useUnavailableObjCClass()
|
|
|
|
// Allow extending a weakly-linked class to conform to a protocol.
|
|
protocol SomeSwiftProtocol { }
|
|
@available(OSX 1066.0, iOS 1066.0, watchOS 1066.0, tvOS 1066.0, *)
|
|
extension UnavailableObjCClass : SomeSwiftProtocol {
|
|
}
|
|
|
|
// CHECK-NEXT: Done
|
|
print("Done")
|