Skip to content

stdlib: make Array implementation internal #3429

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ public func expectEqual<T : Equatable, U : Equatable, V : Equatable>(
expectEqual(expected.2, actual.2, ${trace}, showFrame: false) {$0 == $1}
}

public func expectEqual<T : Equatable, U : Equatable, V : Equatable, W : Equatable>(
_ expected: (T, U, V, W), _ actual: (T, U, V, W), ${TRACE}) {
expectEqual(expected.0, actual.0, ${trace}, showFrame: false) {$0 == $1}
expectEqual(expected.1, actual.1, ${trace}, showFrame: false) {$0 == $1}
expectEqual(expected.2, actual.2, ${trace}, showFrame: false) {$0 == $1}
expectEqual(expected.3, actual.3, ${trace}, showFrame: false) {$0 == $1}
}

public func expectationFailure(
_ reason: String,
trace message: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ internal func _stdlib_NSArray_getObjects(
rangeLength: Int)

extension NSArray {
@nonobjc
public func available_getObjects(
_ objects: AutoreleasingUnsafeMutablePointer<AnyObject?>?, range: NSRange
) {
Expand All @@ -101,6 +102,7 @@ func _stdlib_NSDictionary_getObjects(
)

extension NSDictionary {
@nonobjc
public func available_getObjects(
_ objects: AutoreleasingUnsafeMutablePointer<AnyObject?>?,
andKeys keys: AutoreleasingUnsafeMutablePointer<AnyObject?>?
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/SDK/Foundation/Foundation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ extension Array : _ObjectiveCBridgeable {

@_semantics("convertToObjectiveC")
public func _bridgeToObjectiveC() -> NSArray {
return unsafeBitCast(self._buffer._asCocoaArray(), to: NSArray.self)
return unsafeBitCast(self._bridgeToObjectiveCImpl(), to: NSArray.self)
}

public static func _forceBridgeFromObjectiveC(
Expand Down
85 changes: 43 additions & 42 deletions stdlib/public/core/ArrayBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ internal typealias _ArrayBridgeStorage
= _BridgeStorage<_ContiguousArrayStorageBase, _NSArrayCore>

@_fixed_layout
public struct _ArrayBuffer<Element> : _ArrayBufferProtocol {
internal struct _ArrayBuffer<Element> : _ArrayBufferProtocol {

/// Create an empty buffer.
public init() {
internal init() {
_storage = _ArrayBridgeStorage(native: _emptyArrayStorage)
}

public init(nsArray: _NSArrayCore) {
internal init(nsArray: _NSArrayCore) {
_sanityCheck(_isClassOrObjCExistential(Element.self))
_storage = _ArrayBridgeStorage(objC: nsArray)
}
Expand All @@ -46,7 +46,7 @@ public struct _ArrayBuffer<Element> : _ArrayBufferProtocol {

/// The spare bits that are set when a native array needs deferred
/// element type checking.
var deferredTypeCheckMask: Int { return 1 }
internal var deferredTypeCheckMask: Int { return 1 }

/// Returns an `_ArrayBuffer<U>` containing the same elements,
/// deferring checking each element's `U`-ness until it is accessed.
Expand All @@ -68,7 +68,7 @@ public struct _ArrayBuffer<Element> : _ArrayBufferProtocol {
native: _native._storage, bits: deferredTypeCheckMask))
}

var needsElementTypeCheck: Bool {
internal var needsElementTypeCheck: Bool {
// NSArray's need an element typecheck when the element type isn't AnyObject
return !_isNativeTypeChecked && !(AnyObject.self is Element.Type)
}
Expand All @@ -83,18 +83,18 @@ public struct _ArrayBuffer<Element> : _ArrayBufferProtocol {

extension _ArrayBuffer {
/// Adopt the storage of `source`.
public init(_ source: NativeBuffer, shiftedToStartIndex: Int) {
internal init(_buffer source: NativeBuffer, shiftedToStartIndex: Int) {
_sanityCheck(shiftedToStartIndex == 0, "shiftedToStartIndex must be 0")
_storage = _ArrayBridgeStorage(native: source._storage)
}

/// `true`, if the array is native and does not need a deferred type check.
var arrayPropertyIsNativeTypeChecked: Bool {
internal var arrayPropertyIsNativeTypeChecked: Bool {
return _isNativeTypeChecked
}

/// Returns `true` iff this buffer's storage is uniquely-referenced.
mutating func isUniquelyReferenced() -> Bool {
internal mutating func isUniquelyReferenced() -> Bool {
if !_isClassOrObjCExistential(Element.self) {
return _storage.isUniquelyReferenced_native_noSpareBits()
}
Expand All @@ -103,7 +103,7 @@ extension _ArrayBuffer {

/// Returns `true` iff this buffer's storage is either
/// uniquely-referenced or pinned.
mutating func isUniquelyReferencedOrPinned() -> Bool {
internal mutating func isUniquelyReferencedOrPinned() -> Bool {
if !_isClassOrObjCExistential(Element.self) {
return _storage.isUniquelyReferencedOrPinned_native_noSpareBits()
}
Expand All @@ -114,7 +114,7 @@ extension _ArrayBuffer {
///
/// - Precondition: `_isBridgedToObjectiveC(Element.self)`.
/// O(1) if the element type is bridged verbatim, O(N) otherwise.
public func _asCocoaArray() -> _NSArrayCore {
internal func _asCocoaArray() -> _NSArrayCore {
_sanityCheck(
_isBridgedToObjectiveC(Element.self),
"Array element type is not bridged to Objective-C")
Expand All @@ -126,7 +126,7 @@ extension _ArrayBuffer {
/// `_ContiguousArrayBuffer` that can be grown in-place to allow the self
/// buffer store minimumCapacity elements, returns that buffer.
/// Otherwise, returns `nil`.
public mutating func requestUniqueMutableBackingBuffer(minimumCapacity: Int)
internal mutating func requestUniqueMutableBackingBuffer(minimumCapacity: Int)
-> NativeBuffer? {
if _fastPath(isUniquelyReferenced()) {
let b = _native
Expand All @@ -137,18 +137,18 @@ extension _ArrayBuffer {
return nil
}

public mutating func isMutableAndUniquelyReferenced() -> Bool {
internal mutating func isMutableAndUniquelyReferenced() -> Bool {
return isUniquelyReferenced()
}

public mutating func isMutableAndUniquelyReferencedOrPinned() -> Bool {
internal mutating func isMutableAndUniquelyReferencedOrPinned() -> Bool {
return isUniquelyReferencedOrPinned()
}

/// If this buffer is backed by a `_ContiguousArrayBuffer`
/// containing the same number of elements as `self`, return it.
/// Otherwise, return `nil`.
public func requestNativeBuffer() -> NativeBuffer? {
internal func requestNativeBuffer() -> NativeBuffer? {
if !_isClassOrObjCExistential(Element.self) {
return _native
}
Expand All @@ -175,7 +175,7 @@ extension _ArrayBuffer {
}
}

func _typeCheck(_ subRange: Range<Int>) {
internal func _typeCheck(_ subRange: Range<Int>) {
if !_isClassOrObjCExistential(Element.self) {
return
}
Expand All @@ -194,7 +194,7 @@ extension _ArrayBuffer {
/// memory starting at `target`. Return a pointer "past the end" of the
/// just-initialized memory.
@discardableResult
public func _copyContents(
internal func _copyContents(
subRange bounds: Range<Int>,
initializing target: UnsafeMutablePointer<Element>
) -> UnsafeMutablePointer<Element> {
Expand Down Expand Up @@ -225,7 +225,7 @@ extension _ArrayBuffer {

/// Returns a `_SliceBuffer` containing the given sub-range of elements in
/// `bounds` from this buffer.
public subscript(bounds: Range<Int>) -> _SliceBuffer<Element> {
internal subscript(bounds: Range<Int>) -> _SliceBuffer<Element> {
get {
_typeCheck(bounds)

Expand All @@ -236,7 +236,7 @@ extension _ArrayBuffer {
let boundsCount = bounds.count
if boundsCount == 0 {
return _SliceBuffer(
_ContiguousArrayBuffer<Element>(),
_buffer: _ContiguousArrayBuffer<Element>(),
shiftedToStartIndex: bounds.lowerBound)
}

Expand All @@ -256,14 +256,15 @@ extension _ArrayBuffer {

// No contiguous storage found; we must allocate
let result = _ContiguousArrayBuffer<Element>(
uninitializedCount: boundsCount, minimumCapacity: 0)
_uninitializedCount: boundsCount, minimumCapacity: 0)

// Tell Cocoa to copy the objects into our storage
cocoa.buffer.getObjects(
UnsafeMutablePointer(result.firstElementAddress),
range: _SwiftNSRange(location: bounds.lowerBound, length: boundsCount))

return _SliceBuffer(result, shiftedToStartIndex: bounds.lowerBound)
return _SliceBuffer(
_buffer: result, shiftedToStartIndex: bounds.lowerBound)
}
set {
fatalError("not implemented")
Expand All @@ -273,17 +274,17 @@ extension _ArrayBuffer {
/// A pointer to the first element.
///
/// - Precondition: The elements are known to be stored contiguously.
public var firstElementAddress: UnsafeMutablePointer<Element> {
internal var firstElementAddress: UnsafeMutablePointer<Element> {
_sanityCheck(_isNative, "must be a native buffer")
return _native.firstElementAddress
}

public var firstElementAddressIfContiguous: UnsafeMutablePointer<Element>? {
internal var firstElementAddressIfContiguous: UnsafeMutablePointer<Element>? {
return _fastPath(_isNative) ? firstElementAddress : nil
}

/// The number of elements the buffer stores.
public var count: Int {
internal var count: Int {
@inline(__always)
get {
return _fastPath(_isNative) ? _native.count : _nonNative.count
Expand Down Expand Up @@ -331,13 +332,13 @@ extension _ArrayBuffer {
}

/// The number of elements the buffer can store without reallocation.
public var capacity: Int {
internal var capacity: Int {
return _fastPath(_isNative) ? _native.capacity : _nonNative.count
}

@_versioned
@inline(__always)
func getElement(_ i: Int, wasNativeTypeChecked: Bool) -> Element {
internal func getElement(_ i: Int, wasNativeTypeChecked: Bool) -> Element {
if _fastPath(wasNativeTypeChecked) {
return _nativeTypeChecked[i]
}
Expand All @@ -346,7 +347,7 @@ extension _ArrayBuffer {

@_versioned
@inline(never)
func _getElementSlowPath(_ i: Int) -> AnyObject {
internal func _getElementSlowPath(_ i: Int) -> AnyObject {
_sanityCheck(
_isClassOrObjCExistential(Element.self),
"Only single reference elements can be indexed here.")
Expand All @@ -372,7 +373,7 @@ extension _ArrayBuffer {
}

/// Get or set the value of the ith element.
public subscript(i: Int) -> Element {
internal subscript(i: Int) -> Element {
get {
return getElement(i, wasNativeTypeChecked: _isNativeTypeChecked)
}
Expand All @@ -394,7 +395,7 @@ extension _ArrayBuffer {
/// Call `body(p)`, where `p` is an `UnsafeBufferPointer` over the
/// underlying contiguous storage. If no such storage exists, it is
/// created on-demand.
public func withUnsafeBufferPointer<R>(
internal func withUnsafeBufferPointer<R>(
_ body: @noescape (UnsafeBufferPointer<Element>) throws -> R
) rethrows -> R {
if _fastPath(_isNative) {
Expand All @@ -409,7 +410,7 @@ extension _ArrayBuffer {
/// over the underlying contiguous storage.
///
/// - Precondition: Such contiguous storage exists or the buffer is empty.
public mutating func withUnsafeMutableBufferPointer<R>(
internal mutating func withUnsafeMutableBufferPointer<R>(
_ body: @noescape (UnsafeMutableBufferPointer<Element>) throws -> R
) rethrows -> R {
_sanityCheck(
Expand All @@ -422,22 +423,22 @@ extension _ArrayBuffer {
}

/// An object that keeps the elements stored in this buffer alive.
public var owner: AnyObject {
internal var owner: AnyObject {
return _fastPath(_isNative) ? _native._storage : _nonNative
}

/// An object that keeps the elements stored in this buffer alive.
///
/// - Precondition: This buffer is backed by a `_ContiguousArrayBuffer`.
public var nativeOwner: AnyObject {
internal var nativeOwner: AnyObject {
_sanityCheck(_isNative, "Expect a native array")
return _native._storage
}

/// A value that identifies the storage used by the buffer. Two
/// buffers address the same elements when they have the same
/// identity and count.
public var identity: UnsafePointer<Void> {
internal var identity: UnsafePointer<Void> {
if _isNative {
return _native.identity
}
Expand All @@ -450,7 +451,7 @@ extension _ArrayBuffer {
/// The position of the first element in a non-empty collection.
///
/// In an empty collection, `startIndex == endIndex`.
public var startIndex: Int {
internal var startIndex: Int {
return 0
}

Expand All @@ -459,18 +460,18 @@ extension _ArrayBuffer {
/// `endIndex` is not a valid argument to `subscript`, and is always
/// reachable from `startIndex` by zero or more applications of
/// `index(after:)`.
public var endIndex: Int {
internal var endIndex: Int {
return count
}

public typealias Indices = CountableRange<Int>
internal typealias Indices = CountableRange<Int>

//===--- private --------------------------------------------------------===//
typealias Storage = _ContiguousArrayStorage<Element>
public typealias NativeBuffer = _ContiguousArrayBuffer<Element>
internal typealias Storage = _ContiguousArrayStorage<Element>
internal typealias NativeBuffer = _ContiguousArrayBuffer<Element>

@_versioned
var _isNative: Bool {
internal var _isNative: Bool {
if !_isClassOrObjCExistential(Element.self) {
return true
} else {
Expand All @@ -479,7 +480,7 @@ extension _ArrayBuffer {
}

/// `true`, if the array is native and does not need a deferred type check.
var _isNativeTypeChecked: Bool {
internal var _isNativeTypeChecked: Bool {
if !_isClassOrObjCExistential(Element.self) {
return true
} else {
Expand All @@ -491,7 +492,7 @@ extension _ArrayBuffer {
///
/// - Precondition: `_isNative`.
@_versioned
var _native: NativeBuffer {
internal var _native: NativeBuffer {
return NativeBuffer(
_isClassOrObjCExistential(Element.self)
? _storage.nativeInstance : _storage.nativeInstance_noSpareBits)
Expand All @@ -501,12 +502,12 @@ extension _ArrayBuffer {
///
/// - Precondition: `_isNativeTypeChecked`.
@_versioned
var _nativeTypeChecked: NativeBuffer {
internal var _nativeTypeChecked: NativeBuffer {
return NativeBuffer(_storage.nativeInstance_noSpareBits)
}

@_versioned
var _nonNative: _NSArrayCore {
internal var _nonNative: _NSArrayCore {
@inline(__always)
get {
_sanityCheck(_isClassOrObjCExistential(Element.self))
Expand Down
8 changes: 4 additions & 4 deletions stdlib/public/core/ArrayBufferProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

/// The underlying buffer for an ArrayType conforms to
/// `_ArrayBufferProtocol`. This buffer does not provide value semantics.
public protocol _ArrayBufferProtocol
internal protocol _ArrayBufferProtocol
: MutableCollection, RandomAccessCollection {

associatedtype Indices : RandomAccessCollection = CountableRange<Int>
Expand All @@ -24,7 +24,7 @@ public protocol _ArrayBufferProtocol
init()

/// Adopt the entire buffer, presenting it at the provided `startIndex`.
init(_ buffer: _ContiguousArrayBuffer<Element>, shiftedToStartIndex: Int)
init(_buffer: _ContiguousArrayBuffer<Element>, shiftedToStartIndex: Int)

/// Copy the elements in `bounds` from this buffer into uninitialized
/// memory starting at `target`. Return a pointer "past the end" of the
Expand Down Expand Up @@ -127,11 +127,11 @@ public protocol _ArrayBufferProtocol

extension _ArrayBufferProtocol where Index == Int {

public var subscriptBaseAddress: UnsafeMutablePointer<Element> {
internal var subscriptBaseAddress: UnsafeMutablePointer<Element> {
return firstElementAddress
}

public mutating func replace<C>(
internal mutating func replace<C>(
subRange: Range<Int>,
with newCount: Int,
elementsOf newValues: C
Expand Down
Loading