Files
swift-mirror/stdlib/public/core/Unmanaged.swift
Slava Pestov d65d1d25f9 Sema: Diagnostics for @_inlineable, @_versioned and Swift 4 default arguments model
Piggybacks some resilience diagnostics onto the availability
checking code.

Public and versioned functions with inlineable bodies can only
reference other public and internal entities, since the SIL code
for the function body is serialized and stored as part of the
module.

This includes @_transparent functions, @_inlineable functions,
accessors for @_inlineable storage, @inline(__always) functions,
and in Swift 4 mode, default argument expressions.

The new checks are a source-breaking change, however we don't
guarantee source compatibility for underscored attributes.

The new ABI and tests for the default argument model will come in
subsequent commits.
2017-01-09 16:59:13 -08:00

247 lines
7.9 KiB
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
//
//===----------------------------------------------------------------------===//
/// A type for propagating an unmanaged object reference.
///
/// When you use this type, you become partially responsible for
/// keeping the object alive.
@_fixed_layout
public struct Unmanaged<Instance : AnyObject> {
@_versioned
internal unowned(unsafe) var _value: Instance
@_versioned
@_transparent
internal init(_private: Instance) { _value = _private }
/// Unsafely turns an opaque C pointer into an unmanaged class reference.
///
/// This operation does not change reference counts.
///
/// let str: CFString = Unmanaged.fromOpaque(ptr).takeUnretainedValue()
///
/// - Parameter value: An opaque C pointer.
/// - Returns: An unmanaged class reference to `value`.
@_transparent
public static func fromOpaque(_ value: UnsafeRawPointer) -> Unmanaged {
return Unmanaged(_private: unsafeBitCast(value, to: Instance.self))
}
/// Unsafely converts an unmanaged class reference to a pointer.
///
/// This operation does not change reference counts.
///
/// let str0: CFString = "boxcar"
/// let bits = Unmanaged.passUnretained(str0)
/// let ptr = bits.toOpaque()
///
/// - Returns: An opaque pointer to the value of this unmanaged reference.
@_transparent
public func toOpaque() -> UnsafeMutableRawPointer {
return unsafeBitCast(_value, to: UnsafeMutableRawPointer.self)
}
/// Creates an unmanaged reference with an unbalanced retain.
///
/// The instance passed as `value` will leak if nothing eventually balances
/// the retain.
///
/// This is useful when passing an object to an API which Swift does not know
/// the ownership rules for, but you know that the API expects you to pass
/// the object at +1.
///
/// - Parameter value: A class instance.
/// - Returns: An unmanaged reference to the object passed as `value`.
@_transparent
public static func passRetained(_ value: Instance) -> Unmanaged {
return Unmanaged(_private: value).retain()
}
/// Creates an unmanaged reference without performing an unbalanced
/// retain.
///
/// This is useful when passing a reference to an API which Swift
/// does not know the ownership rules for, but you know that the
/// API expects you to pass the object at +0.
///
/// CFArraySetValueAtIndex(.passUnretained(array), i,
/// .passUnretained(object))
///
/// - Parameter value: A class instance.
/// - Returns: An unmanaged reference to the object passed as `value`.
@_transparent
public static func passUnretained(_ value: Instance) -> Unmanaged {
return Unmanaged(_private: value)
}
/// Gets the value of this unmanaged reference as a managed
/// reference without consuming an unbalanced retain of it.
///
/// This is useful when a function returns an unmanaged reference
/// and you know that you're not responsible for releasing the result.
///
/// - Returns: The object referenced by this `Unmanaged` instance.
public func takeUnretainedValue() -> Instance {
return _value
}
/// Gets the value of this unmanaged reference as a managed
/// reference and consumes an unbalanced retain of it.
///
/// This is useful when a function returns an unmanaged reference
/// and you know that you're responsible for releasing the result.
///
/// - Returns: The object referenced by this `Unmanaged` instance.
public func takeRetainedValue() -> Instance {
let result = _value
release()
return result
}
/// Gets the value of the unmanaged referenced as a managed reference without
/// consuming an unbalanced retain of it and passes it to the closure. Asserts
/// that there is some other reference ('the owning reference') to the
/// instance referenced by the unmanaged reference that guarantees the
/// lifetime of the instance for the duration of the
/// '_withUnsafeGuaranteedRef' call.
///
/// NOTE: You are responsible for ensuring this by making the owning
/// reference's lifetime fixed for the duration of the
/// '_withUnsafeGuaranteedRef' call.
///
/// Violation of this will incur undefined behavior.
///
/// A lifetime of a reference 'the instance' is fixed over a point in the
/// programm if:
///
/// * There exists a global variable that references 'the instance'.
///
/// import Foundation
/// var globalReference = Instance()
/// func aFunction() {
/// point()
/// }
///
/// Or if:
///
/// * There is another managed reference to 'the instance' whose life time is
/// fixed over the point in the program by means of 'withExtendedLifetime'
/// dynamically closing over this point.
///
/// var owningReference = Instance()
/// ...
/// withExtendedLifetime(owningReference) {
/// point($0)
/// }
///
/// Or if:
///
/// * There is a class, or struct instance ('owner') whose lifetime is fixed
/// at the point and which has a stored property that references
/// 'the instance' for the duration of the fixed lifetime of the 'owner'.
///
/// class Owned {
/// }
///
/// class Owner {
/// final var owned: Owned
///
/// func foo() {
/// withExtendedLifetime(self) {
/// doSomething(...)
/// } // Assuming: No stores to owned occur for the dynamic lifetime of
/// // the withExtendedLifetime invocation.
/// }
///
/// func doSomething() {
/// // both 'self' and 'owned''s lifetime is fixed over this point.
/// point(self, owned)
/// }
/// }
///
/// The last rule applies transitively through a chain of stored references
/// and nested structs.
///
/// Examples:
///
/// var owningReference = Instance()
/// ...
/// withExtendedLifetime(owningReference) {
/// let u = Unmanaged.passUnretained(owningReference)
/// for i in 0 ..< 100 {
/// u._withUnsafeGuaranteedRef {
/// $0.doSomething()
/// }
/// }
/// }
///
/// class Owner {
/// final var owned: Owned
///
/// func foo() {
/// withExtendedLifetime(self) {
/// doSomething(Unmanaged.passUnretained(owned))
/// }
/// }
///
/// func doSomething(_ u : Unmanaged<Owned>) {
/// u._withUnsafeGuaranteedRef {
/// $0.doSomething()
/// }
/// }
/// }
public func _withUnsafeGuaranteedRef<Result>(
_ body: (Instance) throws -> Result
) rethrows -> Result {
let (guaranteedInstance, token) = Builtin.unsafeGuaranteed(_value)
let result = try body(guaranteedInstance)
Builtin.unsafeGuaranteedEnd(token)
return result
}
/// Performs an unbalanced retain of the object.
@_transparent
public func retain() -> Unmanaged {
Builtin.retain(_value)
return self
}
/// Performs an unbalanced release of the object.
@_transparent
public func release() {
Builtin.release(_value)
}
#if _runtime(_ObjC)
/// Performs an unbalanced autorelease of the object.
@_transparent
public func autorelease() -> Unmanaged {
Builtin.autorelease(_value)
return self
}
#endif
}
extension Unmanaged {
@available(*, unavailable,
message:"use 'fromOpaque(_: UnsafeRawPointer)' instead")
public static func fromOpaque(_ value: OpaquePointer) -> Unmanaged {
Builtin.unreachable()
}
@available(*, unavailable,
message:"use 'toOpaque() -> UnsafeRawPointer' instead")
public func toOpaque() -> OpaquePointer {
Builtin.unreachable()
}
}