mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Introduce checking of ConcurrentValue conformances: - For structs, check that each stored property conforms to ConcurrentValue - For enums, check that each associated value conforms to ConcurrentValue - For classes, check that each stored property is immutable and conforms to ConcurrentValue Because all of the stored properties / associated values need to be visible for this check to work, limit ConcurrentValue conformances to be in the same source file as the type definition. This checking can be disabled by conforming to a new marker protocol, UnsafeConcurrentValue, that refines ConcurrentValue. UnsafeConcurrentValue otherwise his no specific meaning. This allows both "I know what I'm doing" for types that manage concurrent access themselves as well as enabling retroactive conformance, both of which are fundamentally unsafe but also quite necessary. The bulk of this change ended up being to the standard library, because all conformances of standard library types to the ConcurrentValue protocol needed to be sunk down into the standard library so they would benefit from the checking above. There were numerous little mistakes in the initial pass through the stsandard library types that have now been corrected.
176 lines
5.5 KiB
Swift
176 lines
5.5 KiB
Swift
//===--- CollectionOfOne.swift - A Collection with one element ------------===//
|
|
//
|
|
// 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 collection containing a single element.
|
|
///
|
|
/// You can use a `CollectionOfOne` instance when you need to efficiently
|
|
/// represent a single value as a collection. For example, you can add a
|
|
/// single element to an array by using a `CollectionOfOne` instance with the
|
|
/// concatenation operator (`+`):
|
|
///
|
|
/// let a = [1, 2, 3, 4]
|
|
/// let toAdd = 100
|
|
/// let b = a + CollectionOfOne(toAdd)
|
|
/// // b == [1, 2, 3, 4, 100]
|
|
@frozen // trivial-implementation
|
|
public struct CollectionOfOne<Element> {
|
|
@usableFromInline // trivial-implementation
|
|
internal var _element: Element
|
|
|
|
/// Creates an instance containing just the given element.
|
|
///
|
|
/// - Parameter element: The element to store in the collection.
|
|
@inlinable // trivial-implementation
|
|
public init(_ element: Element) {
|
|
self._element = element
|
|
}
|
|
}
|
|
|
|
extension CollectionOfOne {
|
|
/// An iterator that produces one or zero instances of an element.
|
|
///
|
|
/// `IteratorOverOne` is the iterator for the `CollectionOfOne` type.
|
|
@frozen // trivial-implementation
|
|
public struct Iterator {
|
|
@usableFromInline // trivial-implementation
|
|
internal var _elements: Element?
|
|
|
|
/// Construct an instance that generates `_element!`, or an empty
|
|
/// sequence if `_element == nil`.
|
|
@inlinable // trivial-implementation
|
|
public // @testable
|
|
init(_elements: Element?) {
|
|
self._elements = _elements
|
|
}
|
|
}
|
|
}
|
|
|
|
extension CollectionOfOne.Iterator: IteratorProtocol {
|
|
/// Advances to the next element and returns it, or `nil` if no next element
|
|
/// exists.
|
|
///
|
|
/// Once `nil` has been returned, all subsequent calls return `nil`.
|
|
///
|
|
/// - Returns: The next element in the underlying sequence, if a next element
|
|
/// exists; otherwise, `nil`.
|
|
@inlinable // trivial-implementation
|
|
public mutating func next() -> Element? {
|
|
let result = _elements
|
|
_elements = nil
|
|
return result
|
|
}
|
|
}
|
|
|
|
extension CollectionOfOne: RandomAccessCollection, MutableCollection {
|
|
|
|
public typealias Index = Int
|
|
public typealias Indices = Range<Int>
|
|
public typealias SubSequence = Slice<CollectionOfOne<Element>>
|
|
|
|
/// The position of the first element.
|
|
///
|
|
/// In a `CollectionOfOne` instance, `startIndex` is always `0`.
|
|
@inlinable // trivial-implementation
|
|
public var startIndex: Index {
|
|
return 0
|
|
}
|
|
|
|
/// The "past the end" position---that is, the position one greater than the
|
|
/// last valid subscript argument.
|
|
///
|
|
/// In a `CollectionOfOne` instance, `endIndex` is always `1`.
|
|
@inlinable // trivial-implementation
|
|
public var endIndex: Index {
|
|
return 1
|
|
}
|
|
|
|
/// Returns the position immediately after the given index.
|
|
///
|
|
/// - Parameter i: A valid index of the collection. `i` must be `0`.
|
|
/// - Returns: The index value immediately after `i`.
|
|
@inlinable // trivial-implementation
|
|
public func index(after i: Index) -> Index {
|
|
_precondition(i == startIndex)
|
|
return 1
|
|
}
|
|
|
|
/// Returns the position immediately before the given index.
|
|
///
|
|
/// - Parameter i: A valid index of the collection. `i` must be `1`.
|
|
/// - Returns: The index value immediately before `i`.
|
|
@inlinable // trivial-implementation
|
|
public func index(before i: Index) -> Index {
|
|
_precondition(i == endIndex)
|
|
return 0
|
|
}
|
|
|
|
/// Returns an iterator over the elements of this collection.
|
|
///
|
|
/// - Complexity: O(1)
|
|
@inlinable // trivial-implementation
|
|
public __consuming func makeIterator() -> Iterator {
|
|
return Iterator(_elements: _element)
|
|
}
|
|
|
|
/// Accesses the element at the specified position.
|
|
///
|
|
/// - Parameter position: The position of the element to access. The only
|
|
/// valid position in a `CollectionOfOne` instance is `0`.
|
|
@inlinable // trivial-implementation
|
|
public subscript(position: Int) -> Element {
|
|
_read {
|
|
_precondition(position == 0, "Index out of range")
|
|
yield _element
|
|
}
|
|
_modify {
|
|
_precondition(position == 0, "Index out of range")
|
|
yield &_element
|
|
}
|
|
}
|
|
|
|
@inlinable // trivial-implementation
|
|
public subscript(bounds: Range<Int>) -> SubSequence {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: 0..<1)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(bounds, bounds: 0..<1)
|
|
let n = newValue.count
|
|
_precondition(bounds.count == n, "CollectionOfOne can't be resized")
|
|
if n == 1 { self = newValue.base }
|
|
}
|
|
}
|
|
|
|
/// The number of elements in the collection, which is always one.
|
|
@inlinable // trivial-implementation
|
|
public var count: Int {
|
|
return 1
|
|
}
|
|
}
|
|
|
|
extension CollectionOfOne: CustomDebugStringConvertible {
|
|
/// A textual representation of the collection, suitable for debugging.
|
|
public var debugDescription: String {
|
|
return "CollectionOfOne(\(String(reflecting: _element)))"
|
|
}
|
|
}
|
|
|
|
extension CollectionOfOne: CustomReflectable {
|
|
public var customMirror: Mirror {
|
|
return Mirror(self, children: ["element": _element])
|
|
}
|
|
}
|
|
|
|
extension CollectionOfOne: ConcurrentValue where Element: ConcurrentValue { }
|
|
extension CollectionOfOne.Iterator: ConcurrentValue where Element: ConcurrentValue { }
|