mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
505 lines
17 KiB
Swift
505 lines
17 KiB
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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#if _runtime(_ObjC)
|
|
/// A Swift Array or Dictionary of types conforming to
|
|
/// `_ObjectiveCBridgeable` can be passed to Objective-C as an NSArray or
|
|
/// NSDictionary, respectively. The elements of the resulting NSArray
|
|
/// or NSDictionary will be the result of calling `_bridgeToObjectiveC`
|
|
/// on each element of the source container.
|
|
public protocol _ObjectiveCBridgeable {
|
|
associatedtype _ObjectiveCType : AnyObject
|
|
|
|
/// Returns `true` iff instances of `Self` can be converted to
|
|
/// Objective-C. Even if this method returns `true`, a given
|
|
/// instance of `Self._ObjectiveCType` may, or may not, convert
|
|
/// successfully to `Self`; for example, an `NSArray` will only
|
|
/// convert successfully to `[String]` if it contains only
|
|
/// `NSString`s.
|
|
@warn_unused_result
|
|
static func _isBridgedToObjectiveC() -> Bool
|
|
|
|
// _getObjectiveCType is a workaround: right now protocol witness
|
|
// tables don't include associated types, so we cannot find
|
|
// '_ObjectiveCType.self' from them.
|
|
|
|
/// Must return `_ObjectiveCType.self`.
|
|
@warn_unused_result
|
|
static func _getObjectiveCType() -> Any.Type
|
|
|
|
/// Convert `self` to Objective-C.
|
|
@warn_unused_result
|
|
func _bridgeToObjectiveC() -> _ObjectiveCType
|
|
|
|
/// Bridge from an Objective-C object of the bridged class type to a
|
|
/// value of the Self type.
|
|
///
|
|
/// This bridging operation is used for forced downcasting (e.g.,
|
|
/// via as), and may defer complete checking until later. For
|
|
/// example, when bridging from `NSArray` to `Array<Element>`, we can defer
|
|
/// the checking for the individual elements of the array.
|
|
///
|
|
/// - parameter result: The location where the result is written. The optional
|
|
/// will always contain a value.
|
|
static func _forceBridgeFromObjectiveC(
|
|
source: _ObjectiveCType,
|
|
result: inout Self?
|
|
)
|
|
|
|
/// Try to bridge from an Objective-C object of the bridged class
|
|
/// type to a value of the Self type.
|
|
///
|
|
/// This conditional bridging operation is used for conditional
|
|
/// downcasting (e.g., via as?) and therefore must perform a
|
|
/// complete conversion to the value type; it cannot defer checking
|
|
/// to a later time.
|
|
///
|
|
/// - parameter result: The location where the result is written.
|
|
///
|
|
/// - Returns: `true` if bridging succeeded, `false` otherwise. This redundant
|
|
/// information is provided for the convenience of the runtime's `dynamic_cast`
|
|
/// implementation, so that it need not look into the optional representation
|
|
/// to determine success.
|
|
static func _conditionallyBridgeFromObjectiveC(
|
|
source: _ObjectiveCType,
|
|
result: inout Self?
|
|
) -> Bool
|
|
}
|
|
|
|
//===--- Bridging for metatypes -------------------------------------------===//
|
|
|
|
/// A stand-in for a value of metatype type.
|
|
///
|
|
/// The language and runtime do not yet support protocol conformances for
|
|
/// structural types like metatypes. However, we can use a struct that contains
|
|
/// a metatype, make it conform to _ObjectiveCBridgeable, and its witness table
|
|
/// will be ABI-compatible with one that directly provided conformance to the
|
|
/// metatype type itself.
|
|
public struct _BridgeableMetatype: _ObjectiveCBridgeable {
|
|
internal var value: AnyObject.Type
|
|
|
|
public typealias _ObjectiveCType = AnyObject
|
|
|
|
public static func _isBridgedToObjectiveC() -> Bool {
|
|
return true
|
|
}
|
|
|
|
public static func _getObjectiveCType() -> Any.Type {
|
|
return AnyObject.self
|
|
}
|
|
|
|
public func _bridgeToObjectiveC() -> AnyObject {
|
|
return value
|
|
}
|
|
|
|
public static func _forceBridgeFromObjectiveC(
|
|
source: AnyObject,
|
|
result: inout _BridgeableMetatype?
|
|
) {
|
|
result = _BridgeableMetatype(value: source as! AnyObject.Type)
|
|
}
|
|
|
|
public static func _conditionallyBridgeFromObjectiveC(
|
|
source: AnyObject,
|
|
result: inout _BridgeableMetatype?
|
|
) -> Bool {
|
|
if let type = source as? AnyObject.Type {
|
|
result = _BridgeableMetatype(value: type)
|
|
return true
|
|
}
|
|
|
|
result = nil
|
|
return false
|
|
}
|
|
}
|
|
|
|
|
|
//===--- Bridging facilities written in Objective-C -----------------------===//
|
|
// Functions that must discover and possibly use an arbitrary type's
|
|
// conformance to a given protocol. See ../runtime/Metadata.cpp for
|
|
// implementations.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Attempt to convert `x` to its Objective-C representation.
|
|
///
|
|
/// - If `T` is a class type, it is always bridged verbatim, the function
|
|
/// returns `x`;
|
|
///
|
|
/// - otherwise, `T` conforms to `_ObjectiveCBridgeable`:
|
|
/// + if `T._isBridgedToObjectiveC()` returns `false`, then the
|
|
/// result is empty;
|
|
/// + otherwise, returns the result of `x._bridgeToObjectiveC()`;
|
|
///
|
|
/// - otherwise, the result is empty.
|
|
@warn_unused_result
|
|
public func _bridgeToObjectiveC<T>(x: T) -> AnyObject? {
|
|
if _fastPath(_isClassOrObjCExistential(T.self)) {
|
|
return unsafeBitCast(x, to: AnyObject.self)
|
|
}
|
|
return _bridgeNonVerbatimToObjectiveC(x)
|
|
}
|
|
|
|
@warn_unused_result
|
|
public func _bridgeToObjectiveCUnconditional<T>(x: T) -> AnyObject {
|
|
let optResult: AnyObject? = _bridgeToObjectiveC(x)
|
|
_precondition(optResult != nil,
|
|
"value failed to bridge from Swift type to a Objective-C type")
|
|
return optResult!
|
|
}
|
|
|
|
/// Same as `_bridgeToObjectiveCUnconditional`, but autoreleases the
|
|
/// return value if `T` is bridged non-verbatim.
|
|
@warn_unused_result
|
|
func _bridgeToObjectiveCUnconditionalAutorelease<T>(x: T) -> AnyObject
|
|
{
|
|
if _fastPath(_isClassOrObjCExistential(T.self)) {
|
|
return unsafeBitCast(x, to: AnyObject.self)
|
|
}
|
|
guard let bridged = _bridgeNonVerbatimToObjectiveC(x) else {
|
|
_preconditionFailure(
|
|
"Dictionary key failed to bridge from Swift type to a Objective-C type")
|
|
}
|
|
|
|
_autorelease(bridged)
|
|
return bridged
|
|
}
|
|
|
|
@warn_unused_result
|
|
@_silgen_name("swift_bridgeNonVerbatimToObjectiveC")
|
|
func _bridgeNonVerbatimToObjectiveC<T>(x: T) -> AnyObject?
|
|
|
|
/// Convert `x` from its Objective-C representation to its Swift
|
|
/// representation.
|
|
///
|
|
/// - If `T` is a class type:
|
|
/// - if the dynamic type of `x` is `T` or a subclass of it, it is bridged
|
|
/// verbatim, the function returns `x`;
|
|
/// - otherwise, if `T` conforms to `_ObjectiveCBridgeable`:
|
|
/// + if the dynamic type of `x` is not `T._getObjectiveCType()`
|
|
/// or a subclass of it, trap;
|
|
/// + otherwise, returns the result of `T._forceBridgeFromObjectiveC(x)`;
|
|
/// - otherwise, trap.
|
|
@warn_unused_result
|
|
public func _forceBridgeFromObjectiveC<T>(x: AnyObject, _: T.Type) -> T {
|
|
if _fastPath(_isClassOrObjCExistential(T.self)) {
|
|
return x as! T
|
|
}
|
|
|
|
var result: T?
|
|
_bridgeNonVerbatimFromObjectiveC(x, T.self, &result)
|
|
return result!
|
|
}
|
|
|
|
/// Convert `x` from its Objective-C representation to its Swift
|
|
/// representation.
|
|
@warn_unused_result
|
|
@_silgen_name("_forceBridgeFromObjectiveC_bridgeable")
|
|
public func _forceBridgeFromObjectiveC_bridgeable<T:_ObjectiveCBridgeable>(x: T._ObjectiveCType, _: T.Type) -> T {
|
|
var result: T?
|
|
T._forceBridgeFromObjectiveC(x, result: &result)
|
|
return result!
|
|
}
|
|
|
|
/// Attempt to convert `x` from its Objective-C representation to its Swift
|
|
/// representation.
|
|
///
|
|
/// - If `T` is a class type:
|
|
/// - if the dynamic type of `x` is `T` or a subclass of it, it is bridged
|
|
/// verbatim, the function returns `x`;
|
|
/// - otherwise, if `T` conforms to `_ObjectiveCBridgeable`:
|
|
/// + if `T._isBridgedToObjectiveC()` returns `false`, then the result is
|
|
/// empty;
|
|
/// + otherwise, if the dynamic type of `x` is not `T._getObjectiveCType()`
|
|
/// or a subclass of it, the result is empty;
|
|
/// + otherwise, returns the result of
|
|
/// `T._conditionallyBridgeFromObjectiveC(x)`;
|
|
/// - otherwise, the result is empty.
|
|
@warn_unused_result
|
|
public func _conditionallyBridgeFromObjectiveC<T>(
|
|
x: AnyObject,
|
|
_: T.Type
|
|
) -> T? {
|
|
if _fastPath(_isClassOrObjCExistential(T.self)) {
|
|
return x as? T
|
|
}
|
|
|
|
var result: T?
|
|
_bridgeNonVerbatimFromObjectiveCConditional(x, T.self, &result)
|
|
return result
|
|
}
|
|
|
|
/// Attempt to convert `x` from its Objective-C representation to its Swift
|
|
/// representation.
|
|
@warn_unused_result
|
|
@_silgen_name("_conditionallyBridgeFromObjectiveC_bridgeable")
|
|
public func _conditionallyBridgeFromObjectiveC_bridgeable<T:_ObjectiveCBridgeable>(
|
|
x: T._ObjectiveCType,
|
|
_: T.Type
|
|
) -> T? {
|
|
var result: T?
|
|
T._conditionallyBridgeFromObjectiveC (x, result: &result)
|
|
return result
|
|
}
|
|
|
|
@_silgen_name("swift_bridgeNonVerbatimFromObjectiveC")
|
|
func _bridgeNonVerbatimFromObjectiveC<T>(
|
|
x: AnyObject,
|
|
_ nativeType: T.Type,
|
|
_ result: inout T?
|
|
)
|
|
|
|
/// Runtime optional to conditionally perform a bridge from an object to a value
|
|
/// type.
|
|
///
|
|
/// - parameter result: Will be set to the resulting value if bridging succeeds, and
|
|
/// unchanged otherwise.
|
|
///
|
|
/// - Returns: `true` to indicate success, `false` to indicate failure.
|
|
@_silgen_name("swift_bridgeNonVerbatimFromObjectiveCConditional")
|
|
func _bridgeNonVerbatimFromObjectiveCConditional<T>(
|
|
x: AnyObject,
|
|
_ nativeType: T.Type,
|
|
_ result: inout T?
|
|
) -> Bool
|
|
|
|
/// Determines if values of a given type can be converted to an Objective-C
|
|
/// representation.
|
|
///
|
|
/// - If `T` is a class type, returns `true`;
|
|
/// - otherwise, if `T` conforms to `_ObjectiveCBridgeable`, returns
|
|
/// `T._isBridgedToObjectiveC()`.
|
|
@warn_unused_result
|
|
public func _isBridgedToObjectiveC<T>(_: T.Type) -> Bool {
|
|
if _fastPath(_isClassOrObjCExistential(T.self)) {
|
|
return true
|
|
}
|
|
return _isBridgedNonVerbatimToObjectiveC(T.self)
|
|
}
|
|
|
|
@warn_unused_result
|
|
@_silgen_name("swift_isBridgedNonVerbatimToObjectiveC")
|
|
func _isBridgedNonVerbatimToObjectiveC<T>(_: T.Type) -> Bool
|
|
|
|
/// A type that's bridged "verbatim" does not conform to
|
|
/// `_ObjectiveCBridgeable`, and can have its bits reinterpreted as an
|
|
/// `AnyObject`. When this function returns true, the storage of an
|
|
/// `Array<T>` can be `unsafeBitCast` as an array of `AnyObject`.
|
|
@warn_unused_result
|
|
public func _isBridgedVerbatimToObjectiveC<T>(_: T.Type) -> Bool {
|
|
return _isClassOrObjCExistential(T.self)
|
|
}
|
|
|
|
/// Retrieve the Objective-C type to which the given type is bridged.
|
|
@warn_unused_result
|
|
public func _getBridgedObjectiveCType<T>(_: T.Type) -> Any.Type? {
|
|
if _fastPath(_isClassOrObjCExistential(T.self)) {
|
|
return T.self
|
|
}
|
|
return _getBridgedNonVerbatimObjectiveCType(T.self)
|
|
}
|
|
|
|
@warn_unused_result
|
|
@_silgen_name("swift_getBridgedNonVerbatimObjectiveCType")
|
|
func _getBridgedNonVerbatimObjectiveCType<T>(_: T.Type) -> Any.Type?
|
|
|
|
// -- Pointer argument bridging
|
|
|
|
@_transparent
|
|
internal var _nilNativeObject: AnyObject? {
|
|
return nil
|
|
}
|
|
|
|
/// A mutable pointer-to-ObjC-pointer argument.
|
|
///
|
|
/// This type has implicit conversions to allow passing any of the following
|
|
/// to a C or ObjC API:
|
|
///
|
|
/// - `nil`, which gets passed as a null pointer,
|
|
/// - an inout argument of the referenced type, which gets passed as a pointer
|
|
/// to a writeback temporary with autoreleasing ownership semantics,
|
|
/// - an `UnsafeMutablePointer<Pointee>`, which is passed as-is.
|
|
///
|
|
/// Passing pointers to mutable arrays of ObjC class pointers is not
|
|
/// directly supported. Unlike `UnsafeMutablePointer<Pointee>`,
|
|
/// `AutoreleasingUnsafeMutablePointer<Pointee>` must reference storage that
|
|
/// does not own a reference count to the referenced
|
|
/// value. UnsafeMutablePointer's operations, by contrast, assume that
|
|
/// the referenced storage owns values loaded from or stored to it.
|
|
///
|
|
/// This type does not carry an owner pointer unlike the other C*Pointer types
|
|
/// because it only needs to reference the results of inout conversions, which
|
|
/// already have writeback-scoped lifetime.
|
|
public struct AutoreleasingUnsafeMutablePointer<Pointee /* TODO : class */>
|
|
: Equatable, NilLiteralConvertible, _Pointer {
|
|
|
|
public let _rawValue: Builtin.RawPointer
|
|
|
|
@_transparent
|
|
public // COMPILER_INTRINSIC
|
|
init(_ _rawValue: Builtin.RawPointer) {
|
|
self._rawValue = _rawValue
|
|
}
|
|
|
|
@_transparent
|
|
var _isNull : Bool {
|
|
return UnsafeMutablePointer<Pointee>(self)._isNull
|
|
}
|
|
|
|
/// Access the `Pointee` instance referenced by `self`.
|
|
///
|
|
/// - Precondition: the pointee has been initialized with an instance of type
|
|
/// `Pointee`.
|
|
public var pointee: Pointee {
|
|
/// Retrieve the value the pointer points to.
|
|
@_transparent get {
|
|
_stdlibAssert(!_isNull)
|
|
// We can do a strong load normally.
|
|
return UnsafeMutablePointer<Pointee>(self).pointee
|
|
}
|
|
/// Set the value the pointer points to, copying over the previous value.
|
|
///
|
|
/// AutoreleasingUnsafeMutablePointers are assumed to reference a
|
|
/// value with __autoreleasing ownership semantics, like 'NSFoo**'
|
|
/// in ARC. This autoreleases the argument before trivially
|
|
/// storing it to the referenced memory.
|
|
@_transparent nonmutating set {
|
|
_stdlibAssert(!_isNull)
|
|
// Autorelease the object reference.
|
|
typealias OptionalAnyObject = AnyObject?
|
|
Builtin.retain(unsafeBitCast(newValue, to: OptionalAnyObject.self))
|
|
Builtin.autorelease(unsafeBitCast(newValue, to: OptionalAnyObject.self))
|
|
// Trivially assign it as an OpaquePointer; the pointer references an
|
|
// autoreleasing slot, so retains/releases of the original value are
|
|
// unneeded.
|
|
let p = UnsafeMutablePointer<OpaquePointer>(
|
|
UnsafeMutablePointer<Pointee>(self))
|
|
p.pointee = unsafeBitCast(newValue, to: OpaquePointer.self)
|
|
}
|
|
}
|
|
|
|
/// Access the `i`th element of the raw array pointed to by
|
|
/// `self`.
|
|
///
|
|
/// - Precondition: `self != nil`.
|
|
public subscript(i: Int) -> Pointee {
|
|
@_transparent
|
|
get {
|
|
_stdlibAssert(!_isNull)
|
|
// We can do a strong load normally.
|
|
return (UnsafePointer<Pointee>(self) + i).pointee
|
|
}
|
|
}
|
|
|
|
/// Create an instance initialized with `nil`.
|
|
@_transparent
|
|
public init(nilLiteral: ()) {
|
|
self._rawValue = _nilRawPointer
|
|
}
|
|
|
|
/// Explicit construction from an UnsafeMutablePointer.
|
|
///
|
|
/// This is inherently unsafe; UnsafeMutablePointer assumes the
|
|
/// referenced memory has +1 strong ownership semantics, whereas
|
|
/// AutoreleasingUnsafeMutablePointer implies +0 semantics.
|
|
@_transparent public
|
|
init<U>(_ ptr: UnsafeMutablePointer<U>) {
|
|
self._rawValue = ptr._rawValue
|
|
}
|
|
|
|
/// Explicit construction from a UnsafePointer.
|
|
///
|
|
/// This is inherently unsafe because UnsafePointers do not imply
|
|
/// mutability.
|
|
@_transparent
|
|
init<U>(_ ptr: UnsafePointer<U>) {
|
|
self._rawValue = ptr._rawValue
|
|
}
|
|
}
|
|
|
|
extension AutoreleasingUnsafeMutablePointer : CustomDebugStringConvertible {
|
|
/// A textual representation of `self`, suitable for debugging.
|
|
public var debugDescription: String {
|
|
return _rawPointerToString(_rawValue)
|
|
}
|
|
}
|
|
|
|
@_transparent
|
|
@warn_unused_result
|
|
public func == <Pointee> (
|
|
lhs: AutoreleasingUnsafeMutablePointer<Pointee>,
|
|
rhs: AutoreleasingUnsafeMutablePointer<Pointee>
|
|
) -> Bool {
|
|
return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
|
|
}
|
|
|
|
internal struct _CocoaFastEnumerationStackBuf {
|
|
// Clang uses 16 pointers. So do we.
|
|
internal var _item0: Builtin.RawPointer
|
|
internal var _item1: Builtin.RawPointer
|
|
internal var _item2: Builtin.RawPointer
|
|
internal var _item3: Builtin.RawPointer
|
|
internal var _item4: Builtin.RawPointer
|
|
internal var _item5: Builtin.RawPointer
|
|
internal var _item6: Builtin.RawPointer
|
|
internal var _item7: Builtin.RawPointer
|
|
internal var _item8: Builtin.RawPointer
|
|
internal var _item9: Builtin.RawPointer
|
|
internal var _item10: Builtin.RawPointer
|
|
internal var _item11: Builtin.RawPointer
|
|
internal var _item12: Builtin.RawPointer
|
|
internal var _item13: Builtin.RawPointer
|
|
internal var _item14: Builtin.RawPointer
|
|
internal var _item15: Builtin.RawPointer
|
|
|
|
@_transparent
|
|
internal var count: Int {
|
|
return 16
|
|
}
|
|
|
|
internal init() {
|
|
_item0 = _nilRawPointer
|
|
_item1 = _item0
|
|
_item2 = _item0
|
|
_item3 = _item0
|
|
_item4 = _item0
|
|
_item5 = _item0
|
|
_item6 = _item0
|
|
_item7 = _item0
|
|
_item8 = _item0
|
|
_item9 = _item0
|
|
_item10 = _item0
|
|
_item11 = _item0
|
|
_item12 = _item0
|
|
_item13 = _item0
|
|
_item14 = _item0
|
|
_item15 = _item0
|
|
|
|
_sanityCheck(sizeofValue(self) >= sizeof(Builtin.RawPointer.self) * count)
|
|
}
|
|
}
|
|
|
|
extension AutoreleasingUnsafeMutablePointer {
|
|
@available(*, unavailable, renamed="Pointee")
|
|
public typealias Memory = Pointee
|
|
|
|
@available(*, unavailable, renamed="pointee")
|
|
public var memory: Pointee {
|
|
fatalError("unavailable function can't be called")
|
|
}
|
|
|
|
@available(*, unavailable, message="Removed in Swift 3. Please use nil literal instead.")
|
|
public init() {
|
|
fatalError("unavailable function can't be called")
|
|
}
|
|
}
|
|
#endif
|