diff --git a/docs/StandardLibraryProgrammersManual.md b/docs/StandardLibraryProgrammersManual.md index 059fdb07fe034..99c612d9a0e5d 100644 --- a/docs/StandardLibraryProgrammersManual.md +++ b/docs/StandardLibraryProgrammersManual.md @@ -12,10 +12,232 @@ In this document, "stdlib" refers to the core standard library (`stdlib/public/c ### Formatting Conventions -The stdlib currently has a hard line length limit of 80 characters. To break long lines, please closely follow the indentation conventions you see in the existing codebase. (FIXME: Describe.) +The Standard Library codebase has some uniformly applied formatting conventions. While these aren't currently automatically enforced, we still expect these conventions to be followed in every PR, including draft PRs. (PRs are first and foremost intended to be read/reviewed by people, and it's crucial that trivial formatting issues don't get in the way of understanding proposed changes.) + +Some of this code is very subtle, and its presentation matters greatly. Effort spent on getting formatting _just right_ is time very well spent: new code we add is going to be repeatedly read and re-read by many people, and it's important that code is presented in a way that helps understanding it. + +#### Line Breaking + +The stdlib currently has a hard line length limit of 80 characters. This allows code to be easily read in environments that don't gracefully handle long lines, including (especially!) code reviews on GitHub. We use two spaces as the unit of indentation. We don't use tabs. +To break long lines, please closely follow the indentation conventions you see in the existing codebase. (FIXME: Describe in detail.) + +Our primary rule is that if we need to insert a line break anywhere in the middle of a list (such as arguments, tuple or array/dictionary literals, generic type parameters, etc.), then we must go all the way and put each item on its own line, indented by +1 unit, even if some of the items would fit on a single line together. + +The rationale for this is that line breaks tend to put strong visual emphasis on the item that follows them, risking subsequent items on the same line to be glanced over during review. For example, see how easy it is to accidentally miss `arg2` in the second example below. + +```swift +// BAD (completely unreadable) +@inlinable public func foobar(_ arg1: Result, arg2: Int, _ arg3: (Result, Element) throws -> Result) rethrows -> Result { + ... +} + +// BAD (arg2 is easily missed) +@inlinable +public func foobar( + _ arg1: Result, arg2: Int, // ☹️ + _ arg3: (Result, Element) throws -> Result +) rethrows -> Result { + +// GOOD +@inlinable +public func foobar( + _ arg1: Result, + arg2: Int, + _ arg3: (Result, Element) throws -> Result +) rethrows -> Result { + ... +} +``` + +As a special case, function arguments that are very tightly coupled together are sometimes kept on the same line. The typical example for this is a pair of defaulted file/line arguments that track the caller's source position: + +```swift +// OK +internal func _preconditionFailure( + _ message: StaticString = StaticString(), + file: StaticString = #file, line: UInt = #line +) -> Never { + ... +} + +// Also OK +internal func _preconditionFailure( + _ message: StaticString = StaticString(), + file: StaticString = #file, + line: UInt = #line +) -> Never { + ... +} +``` + +(When in doubt, err on the side of adding more line breaks.) + + +For lists that have delimiter characters (`(`/`)`, `[`/`]`, `<`/`>`, etc.), we prefer to put a line break both *after* the opening delimiter, and *before* the closing delimiter. +However, within function bodies, it's okay to omit the line break before the closing delimiter. + +```swift +// GOOD: +func foo( + input: S, + transform: (S.Element) -> throws T +) -> [S.Element] { // Note: there *must* be a line break before the ')' + ... + someLongFunctionCall( + on: S, + startingAt: i, + stride: 32) // Note: the break before the closing paren is optional +} +``` + +If the entire contents of a list fit on a single line, it is okay to only break at the delimiters. That said, it is also acceptable to put breaks around each item: + +```swift +// GOOD: +@_alwaysEmitIntoClient +internal func _parseIntegerDigits( + ascii codeUnits: UnsafeBufferPointer, radix: Int, isNegative: Bool +) -> Result? { + ... +} + +// ALSO GOOD: +@_alwaysEmitIntoClient +internal func _parseIntegerDigits( + ascii codeUnits: UnsafeBufferPointer, + radix: Int, + isNegative: Bool +) -> Result? { + ... +} +``` + +The rules typically don't require breaking lines that don't exceed the length limit; but if you find it helps understanding, feel free to do so anyway. + +```swift +// OK +guard let foo = foo else { return false } + +// Also OK +guard let foo = foo else { + return false +} +``` + +Historically, we had a one (1) exception to the line limit, which is that we allowed string literals to go over the margin. Now that Swift has multi-line string literals, we could start breaking overlong ones. However, multiline literals can be a bit heavy visually, while in most cases the string is a precondition failure message, which doesn't necessarily need to be emphasized as much -- so the old exception still applies: + +```swift + // OK + _precondition( | + buffer.baseAddress == firstElementAddress, | + "Can't reassign buffer in Array(unsafeUninitializedCapacity:initializingWith:)" + ) | + | + // Also OK, although spending 4 lines on the message is a bit much | + _precondition( | + buffer.baseAddress == firstElementAddress, | + """" | + Can't reassign buffer in \ | + Array(unsafeUninitializedCapacity:initializingWith:) | + """" | + ) | +``` + +In every other case, long lines must be broken up. We expect this rule to be strictly observed. + + +#### Presentation of Type Definitions + +To ease reading/understanding type declarations, we prefer to define members in the following order: + +1. Crucial type aliases and nested types, not exceeding a handful of lines in length +2. Stored properties +3. Initializers +4. Any other instance members (methods, computed properties, etc) + +Please keep all stored properties together in a single uninterrupted list, followed immediately by the type's most crucial initializer(s). Put these as close to the top of the type declaration as possible -- we don't want to force readers to scroll around to find these core definitions. + +We also have some recommendations for defining other members. These aren't strict rules, as the best way to present definitions varies; but it usually makes sense to break up the implementation into easily digestable, logical chunks. + +- In general, it is a good idea to keep the main `struct`/`class` definiton as short as possible: preferably it should consist of the type's stored properties and a handful of critical initializers, and nothing else. + +- Everything else should go in standalone extensions, arranged by logical theme. For example, it's often nice to define protocol conformances in dedicated extensions. If it makes sense, feel free to add a comment to title these sectioning extensions. + +- Think about what order you present these sections -- put related conformances together, follow some didactic progression, etc. E.g, conformance definitions for closely related protocols such as `Equatable`/`Hashable`/`Comparable` should be kept very close to each other, for easy referencing. + +- In some cases, it can also work well to declare the most essential protocol conformances directly on the type definition; feel free to do so if it helps understanding. (You can still implement requirements in separate extensions in this case, or you can do it within the main declaration.) + +- It's okay for the core type declaration to forward reference large nested types or static members that are defined in subsequent extensions. It's often a good idea to define these in an extension immediately following the type declaration, but this is not a strict rule. + +Extensions are a nice way to break up the implementation into easily digestable chunks, but they aren't the only way. The goal is to make things easy to understand -- if a type is small enough, it may be best to list every member directly in the `struct`/`class` definition, while for huge types it often makes more sense to break them up into a handful of separate source files instead. + +```swift +// BAD (a jumbled mess) +struct Foo: RandomAccessCollection, Hashable { + var count: Int { ... } + + struct Iterator: IteratorProtocol { /* hundreds of lines */ } + + class _Storage { /* even more lines */ } + + static func _createStorage(_ foo: Int, _ bar: Double) -> _Storage { ... } + + func hash(into hasher: inout Hasher) { ... } + + func makeIterator() -> Iterator { ... } + + /* more stuff */ + + init(foo: Int, bar: Double) { + _storage = Self._createStorage(foo, bar) + } + + static func ==(left: Self, right: Self) -> Bool { ... } + + var _storage: _Storage +} + +// GOOD +struct Foo { + var _storage: _Storage + + init(foo: Int, bar: Double) { ... } +} + +extension Foo { + class _Storage { /* even more lines */ } + + static func _createStorage(_ foo: Int, _ bar: Double) -> _Storage { ... } +} + +extension Foo: Equatable { + static func ==(left: Self, right: Self) -> Bool { ... } +} + +extension Foo: Hashable { + func hash(into hasher: inout Hasher) { ... } +} + +extension Foo: Sequence { + struct Iterator: IteratorProtocol { /* hundreds of lines */ } + + func makeIterator() -> Iterator { ... } + ... +} + +extension Foo: RandomAccessCollection { + var count: Int { ... } + ... +} + +extension Foo { + /* more stuff */ +} +``` + ### Public APIs #### Core Standard Library diff --git a/stdlib/public/core/ArrayBuffer.swift b/stdlib/public/core/ArrayBuffer.swift index 614e4ad63a111..683f9f919463a 100644 --- a/stdlib/public/core/ArrayBuffer.swift +++ b/stdlib/public/core/ArrayBuffer.swift @@ -25,6 +25,13 @@ internal typealias _ArrayBridgeStorage @usableFromInline @frozen internal struct _ArrayBuffer: _ArrayBufferProtocol { + @usableFromInline + internal var _storage: _ArrayBridgeStorage + + @inlinable + internal init(storage: _ArrayBridgeStorage) { + _storage = storage + } /// Create an empty buffer. @inlinable @@ -74,15 +81,6 @@ internal struct _ArrayBuffer: _ArrayBufferProtocol { // NSArray's need an element typecheck when the element type isn't AnyObject return !_isNativeTypeChecked && !(AnyObject.self is Element.Type) } - - //===--- private --------------------------------------------------------===// - @inlinable - internal init(storage: _ArrayBridgeStorage) { - _storage = storage - } - - @usableFromInline - internal var _storage: _ArrayBridgeStorage } extension _ArrayBuffer { diff --git a/stdlib/public/core/BridgingBuffer.swift b/stdlib/public/core/BridgingBuffer.swift index 5e6e28a5a6e84..db83773ee7d53 100644 --- a/stdlib/public/core/BridgingBuffer.swift +++ b/stdlib/public/core/BridgingBuffer.swift @@ -11,8 +11,9 @@ //===----------------------------------------------------------------------===// internal struct _BridgingBufferHeader { - internal init(_ count: Int) { self.count = count } internal var count: Int + + internal init(_ count: Int) { self.count = count } } // NOTE: older runtimes called this class _BridgingBufferStorage. diff --git a/stdlib/public/core/Codable.swift b/stdlib/public/core/Codable.swift index 6c6c0e2b7f38d..0b13e55bf3ea9 100644 --- a/stdlib/public/core/Codable.swift +++ b/stdlib/public/core/Codable.swift @@ -3369,8 +3369,8 @@ public enum DecodingError: Error { // The following extensions allow for easier error construction. internal struct _GenericIndexKey: CodingKey, Sendable { - internal var stringValue: String - internal var intValue: Int? + internal var stringValue: String + internal var intValue: Int? internal init?(stringValue: String) { return nil diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift index 12ed227ce3e03..053cfff10d4e1 100644 --- a/stdlib/public/core/Collection.swift +++ b/stdlib/public/core/Collection.swift @@ -72,18 +72,18 @@ public struct IndexingIterator { @usableFromInline internal var _position: Elements.Index + /// Creates an iterator over the given collection. @inlinable @inline(__always) - /// Creates an iterator over the given collection. public /// @testable init(_elements: Elements) { self._elements = _elements self._position = _elements.startIndex } + /// Creates an iterator over the given collection. @inlinable @inline(__always) - /// Creates an iterator over the given collection. public /// @testable init(_elements: Elements, _position: Elements.Index) { self._elements = _elements diff --git a/stdlib/public/core/CollectionDifference.swift b/stdlib/public/core/CollectionDifference.swift index 6f769ff0ca7ad..c850eb2eea9fc 100644 --- a/stdlib/public/core/CollectionDifference.swift +++ b/stdlib/public/core/CollectionDifference.swift @@ -72,59 +72,6 @@ public struct CollectionDifference { /// The removals contained by this difference, from lowest offset to highest. public let removals: [Change] - /// The public initializer calls this function to ensure that its parameter - /// meets the conditions set in its documentation. - /// - /// - Parameter changes: a collection of `CollectionDifference.Change` - /// instances intended to represent a valid state transition for - /// `CollectionDifference`. - /// - /// - Returns: whether the parameter meets the following criteria: - /// - /// 1. All insertion offsets are unique - /// 2. All removal offsets are unique - /// 3. All associations between insertions and removals are symmetric - /// - /// Complexity: O(`changes.count`) - private static func _validateChanges( - _ changes : Changes - ) -> Bool where Changes.Element == Change { - if changes.isEmpty { return true } - - var insertAssocToOffset = Dictionary() - var removeOffsetToAssoc = Dictionary() - var insertOffset = Set() - var removeOffset = Set() - - for change in changes { - let offset = change._offset - if offset < 0 { return false } - - switch change { - case .remove(_, _, _): - if removeOffset.contains(offset) { return false } - removeOffset.insert(offset) - case .insert(_, _, _): - if insertOffset.contains(offset) { return false } - insertOffset.insert(offset) - } - - if let assoc = change._associatedOffset { - if assoc < 0 { return false } - switch change { - case .remove(_, _, _): - if removeOffsetToAssoc[offset] != nil { return false } - removeOffsetToAssoc[offset] = assoc - case .insert(_, _, _): - if insertAssocToOffset[assoc] != nil { return false } - insertAssocToOffset[assoc] = offset - } - } - } - - return removeOffsetToAssoc == insertAssocToOffset - } - /// Creates a new collection difference from a collection of changes. /// /// To find the difference between two collections, use the @@ -201,6 +148,59 @@ public struct CollectionDifference { insertions = Array(sortedChanges[firstInsertIndex..( + _ changes : Changes + ) -> Bool where Changes.Element == Change { + if changes.isEmpty { return true } + + var insertAssocToOffset = Dictionary() + var removeOffsetToAssoc = Dictionary() + var insertOffset = Set() + var removeOffset = Set() + + for change in changes { + let offset = change._offset + if offset < 0 { return false } + + switch change { + case .remove(_, _, _): + if removeOffset.contains(offset) { return false } + removeOffset.insert(offset) + case .insert(_, _, _): + if insertOffset.contains(offset) { return false } + insertOffset.insert(offset) + } + + if let assoc = change._associatedOffset { + if assoc < 0 { return false } + switch change { + case .remove(_, _, _): + if removeOffsetToAssoc[offset] != nil { return false } + removeOffsetToAssoc[offset] = assoc + case .insert(_, _, _): + if insertAssocToOffset[assoc] != nil { return false } + insertAssocToOffset[assoc] = offset + } + } + } + + return removeOffsetToAssoc == insertAssocToOffset + } + public func inverse() -> Self { return CollectionDifference(_validatedChanges: self.map { c in switch c { diff --git a/stdlib/public/core/ContiguousArrayBuffer.swift b/stdlib/public/core/ContiguousArrayBuffer.swift index 270d3b1b153d3..232b539f8ddb6 100644 --- a/stdlib/public/core/ContiguousArrayBuffer.swift +++ b/stdlib/public/core/ContiguousArrayBuffer.swift @@ -253,6 +253,8 @@ internal final class _ContiguousArrayStorage< @usableFromInline @frozen internal struct _ContiguousArrayBuffer: _ArrayBufferProtocol { + @usableFromInline + internal var _storage: __ContiguousArrayStorageBase /// Make a buffer with uninitialized elements. After using this /// method, you must either initialize the `count` elements at the @@ -846,9 +848,6 @@ internal struct _ContiguousArrayBuffer: _ArrayBufferProtocol { } return true } - - @usableFromInline - internal var _storage: __ContiguousArrayStorageBase } /// Append the elements of `rhs` to `lhs`. diff --git a/stdlib/public/core/Diffing.swift b/stdlib/public/core/Diffing.swift index 194122669fba9..2cc39953ee184 100644 --- a/stdlib/public/core/Diffing.swift +++ b/stdlib/public/core/Diffing.swift @@ -193,13 +193,6 @@ private struct _V { private let isOdd: Bool #endif - // The way negative indexes are implemented is by interleaving them in the empty slots between the valid positive indexes - @inline(__always) private static func transform(_ index: Int) -> Int { - // -3, -1, 1, 3 -> 3, 1, 0, 2 -> 0...3 - // -2, 0, 2 -> 2, 0, 1 -> 0...2 - return (index <= 0 ? -index : index &- 1) - } - init(maxIndex largest: Int) { #if INTERNAL_CHECKS_ENABLED _internalInvariant(largest >= 0) @@ -208,6 +201,13 @@ private struct _V { a = [Int](repeating: 0, count: largest + 1) } + // The way negative indexes are implemented is by interleaving them in the empty slots between the valid positive indexes + @inline(__always) private static func transform(_ index: Int) -> Int { + // -3, -1, 1, 3 -> 3, 1, 0, 2 -> 0...3 + // -2, 0, 2 -> 2, 0, 1 -> 0...2 + return (index <= 0 ? -index : index &- 1) + } + subscript(index: Int) -> Int { get { #if INTERNAL_CHECKS_ENABLED diff --git a/stdlib/public/core/DropWhile.swift b/stdlib/public/core/DropWhile.swift index 090fc9a715b2c..2efa82b61a5f1 100644 --- a/stdlib/public/core/DropWhile.swift +++ b/stdlib/public/core/DropWhile.swift @@ -15,7 +15,12 @@ @frozen // lazy-performance public struct LazyDropWhileSequence { public typealias Element = Base.Element - + + @usableFromInline // lazy-performance + internal var _base: Base + @usableFromInline // lazy-performance + internal let _predicate: (Element) -> Bool + /// Create an instance with elements `transform(x)` for each element /// `x` of base. @inlinable // lazy-performance @@ -24,10 +29,6 @@ public struct LazyDropWhileSequence { self._predicate = predicate } - @usableFromInline // lazy-performance - internal var _base: Base - @usableFromInline // lazy-performance - internal let _predicate: (Element) -> Bool } extension LazyDropWhileSequence { @@ -40,12 +41,6 @@ extension LazyDropWhileSequence { @frozen // lazy-performance public struct Iterator { public typealias Element = Base.Element - - @inlinable // lazy-performance - internal init(_base: Base.Iterator, predicate: @escaping (Element) -> Bool) { - self._base = _base - self._predicate = predicate - } @usableFromInline // lazy-performance internal var _predicateHasFailed = false @@ -53,6 +48,12 @@ extension LazyDropWhileSequence { internal var _base: Base.Iterator @usableFromInline // lazy-performance internal let _predicate: (Element) -> Bool + + @inlinable // lazy-performance + internal init(_base: Base.Iterator, predicate: @escaping (Element) -> Bool) { + self._base = _base + self._predicate = predicate + } } } diff --git a/stdlib/public/core/ExistentialCollection.swift b/stdlib/public/core/ExistentialCollection.swift index d22174940e1c5..26bbc9692aee6 100644 --- a/stdlib/public/core/ExistentialCollection.swift +++ b/stdlib/public/core/ExistentialCollection.swift @@ -108,6 +108,9 @@ extension AnyIterator: Sequence { } @usableFromInline @frozen internal struct _ClosureBasedIterator: IteratorProtocol { + @usableFromInline + internal let _body: () -> Element? + @inlinable internal init(_ body: @escaping () -> Element?) { self._body = body @@ -115,9 +118,6 @@ internal struct _ClosureBasedIterator: IteratorProtocol { @inlinable internal func next() -> Element? { return _body() } - - @usableFromInline - internal let _body: () -> Element? } @_fixed_layout diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb index d747b74a8cbb4..cac851d81177d 100644 --- a/stdlib/public/core/FloatingPointTypes.swift.gyb +++ b/stdlib/public/core/FloatingPointTypes.swift.gyb @@ -286,6 +286,12 @@ extension ${Self}: BinaryFloatingPoint { @usableFromInline internal var _storage: (UInt64, UInt16, /* pad */ UInt16, UInt16, UInt16) + @usableFromInline + @_transparent + internal init(explicitSignificand: UInt64, signAndExponent: UInt16) { + _storage = (explicitSignificand, signAndExponent, 0, 0, 0) + } + @usableFromInline @_transparent internal var explicitSignificand: UInt64 { return _storage.0 } @@ -305,12 +311,6 @@ extension ${Self}: BinaryFloatingPoint { internal var exponentBitPattern: UInt { return UInt(signAndExponent) & 0x7fff } - - @usableFromInline - @_transparent - internal init(explicitSignificand: UInt64, signAndExponent: UInt16) { - _storage = (explicitSignificand, signAndExponent, 0, 0, 0) - } } @inlinable @@ -1279,6 +1279,7 @@ extension ${Self}: Strideable { % if bits != 16: internal struct _${Self}AnyHashableBox: _AnyHashableBox { internal typealias Base = ${Self} + internal let _value: Base internal init(_ value: Base) { diff --git a/stdlib/public/core/IntegerTypes.swift.gyb b/stdlib/public/core/IntegerTypes.swift.gyb index b4b2083b9df0d..8ef22074481a4 100644 --- a/stdlib/public/core/IntegerTypes.swift.gyb +++ b/stdlib/public/core/IntegerTypes.swift.gyb @@ -1093,6 +1093,7 @@ public struct ${Self} /// A type that represents an integer literal. public typealias IntegerLiteralType = ${Self} + public var _value: Builtin.Int${bits} @_transparent public init(_builtinIntegerLiteral x: Builtin.IntLiteral) { @@ -1626,8 +1627,6 @@ ${assignmentOperatorComment(x.operator, True)} // Implementation details - public var _value: Builtin.Int${bits} - % if self_type.is_word: @_transparent public // @testable diff --git a/stdlib/public/core/Join.swift b/stdlib/public/core/Join.swift index c906a5f206ea5..c6e5543e3fc08 100644 --- a/stdlib/public/core/Join.swift +++ b/stdlib/public/core/Join.swift @@ -39,15 +39,6 @@ extension JoinedSequence { /// by a base iterator, concatenated using a given separator. @frozen // lazy-performance public struct Iterator { - @usableFromInline // lazy-performance - internal var _base: Base.Iterator - @usableFromInline // lazy-performance - internal var _inner: Base.Element.Iterator? - @usableFromInline // lazy-performance - internal var _separatorData: ContiguousArray - @usableFromInline // lazy-performance - internal var _separator: ContiguousArray.Iterator? - @frozen // lazy-performance @usableFromInline // lazy-performance internal enum _JoinIteratorState { @@ -56,10 +47,19 @@ extension JoinedSequence { case generatingSeparator case end } + + @usableFromInline // lazy-performance + internal var _base: Base.Iterator + @usableFromInline // lazy-performance + internal var _inner: Base.Element.Iterator? + @usableFromInline // lazy-performance + internal var _separatorData: ContiguousArray + @usableFromInline // lazy-performance + internal var _separator: ContiguousArray.Iterator? @usableFromInline // lazy-performance internal var _state: _JoinIteratorState = .start - /// Creates a sequence that presents the elements of `base` sequences + /// Creates an iterator that presents the elements of `base` sequences /// concatenated using `separator`. /// /// - Complexity: O(`separator.count`). @@ -69,7 +69,7 @@ extension JoinedSequence { self._base = base self._separatorData = ContiguousArray(separator) } - } + } } extension JoinedSequence.Iterator: IteratorProtocol { diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift index 832a6b7a67bdb..2d8f03974253b 100644 --- a/stdlib/public/core/KeyPath.swift +++ b/stdlib/public/core/KeyPath.swift @@ -610,6 +610,10 @@ internal struct ComputedArgumentWitnessesPtr { internal enum KeyPathComponent: Hashable { internal struct ArgumentRef { + internal var data: UnsafeRawBufferPointer + internal var witnesses: ComputedArgumentWitnessesPtr + internal var witnessSizeAdjustment: Int + internal init( data: UnsafeRawBufferPointer, witnesses: ComputedArgumentWitnessesPtr, @@ -619,10 +623,6 @@ internal enum KeyPathComponent: Hashable { self.witnesses = witnesses self.witnessSizeAdjustment = witnessSizeAdjustment } - - internal var data: UnsafeRawBufferPointer - internal var witnesses: ComputedArgumentWitnessesPtr - internal var witnessSizeAdjustment: Int } /// The keypath projects within the storage of the outer value, like a @@ -879,20 +879,97 @@ internal enum KeyPathComputedIDResolution { } internal struct RawKeyPathComponent { + internal var header: Header + internal var body: UnsafeRawBufferPointer + internal init(header: Header, body: UnsafeRawBufferPointer) { self.header = header self.body = body } - internal var header: Header - internal var body: UnsafeRawBufferPointer - @_transparent static var metadataAccessorPtrAuthKey: UInt64 { return UInt64(_SwiftKeyPath_ptrauth_MetadataAccessor) } internal struct Header { + internal var _value: UInt32 + + init(discriminator: UInt32, payload: UInt32) { + _value = 0 + self.discriminator = discriminator + self.payload = payload + } + + internal var discriminator: UInt32 { + get { + return (_value & Header.discriminatorMask) >> Header.discriminatorShift + } + set { + let shifted = newValue << Header.discriminatorShift + _internalInvariant(shifted & Header.discriminatorMask == shifted, + "discriminator doesn't fit") + _value = _value & ~Header.discriminatorMask | shifted + } + } + internal var payload: UInt32 { + get { + return _value & Header.payloadMask + } + set { + _internalInvariant(newValue & Header.payloadMask == newValue, + "payload too big") + _value = _value & ~Header.payloadMask | newValue + } + } + internal var storedOffsetPayload: UInt32 { + get { + _internalInvariant(kind == .struct || kind == .class, + "not a stored component") + return _value & Header.storedOffsetPayloadMask + } + set { + _internalInvariant(kind == .struct || kind == .class, + "not a stored component") + _internalInvariant(newValue & Header.storedOffsetPayloadMask == newValue, + "payload too big") + _value = _value & ~Header.storedOffsetPayloadMask | newValue + } + } + internal var endOfReferencePrefix: Bool { + get { + return _value & Header.endOfReferencePrefixFlag != 0 + } + set { + if newValue { + _value |= Header.endOfReferencePrefixFlag + } else { + _value &= ~Header.endOfReferencePrefixFlag + } + } + } + + internal var kind: KeyPathComponentKind { + switch (discriminator, payload) { + case (Header.externalTag, _): + return .external + case (Header.structTag, _): + return .struct + case (Header.classTag, _): + return .class + case (Header.computedTag, _): + return .computed + case (Header.optionalTag, Header.optionalChainPayload): + return .optionalChain + case (Header.optionalTag, Header.optionalWrapPayload): + return .optionalWrap + case (Header.optionalTag, Header.optionalForcePayload): + return .optionalForce + default: + _internalInvariantFailure("invalid header") + } + } + internal static var payloadMask: UInt32 { return _SwiftKeyPathComponentHeader_PayloadMask } @@ -1049,77 +1126,6 @@ internal struct RawKeyPathComponent { _internalInvariantFailure("invalid key path resolution") } } - - internal var _value: UInt32 - - internal var discriminator: UInt32 { - get { - return (_value & Header.discriminatorMask) >> Header.discriminatorShift - } - set { - let shifted = newValue << Header.discriminatorShift - _internalInvariant(shifted & Header.discriminatorMask == shifted, - "discriminator doesn't fit") - _value = _value & ~Header.discriminatorMask | shifted - } - } - internal var payload: UInt32 { - get { - return _value & Header.payloadMask - } - set { - _internalInvariant(newValue & Header.payloadMask == newValue, - "payload too big") - _value = _value & ~Header.payloadMask | newValue - } - } - internal var storedOffsetPayload: UInt32 { - get { - _internalInvariant(kind == .struct || kind == .class, - "not a stored component") - return _value & Header.storedOffsetPayloadMask - } - set { - _internalInvariant(kind == .struct || kind == .class, - "not a stored component") - _internalInvariant(newValue & Header.storedOffsetPayloadMask == newValue, - "payload too big") - _value = _value & ~Header.storedOffsetPayloadMask | newValue - } - } - internal var endOfReferencePrefix: Bool { - get { - return _value & Header.endOfReferencePrefixFlag != 0 - } - set { - if newValue { - _value |= Header.endOfReferencePrefixFlag - } else { - _value &= ~Header.endOfReferencePrefixFlag - } - } - } - - internal var kind: KeyPathComponentKind { - switch (discriminator, payload) { - case (Header.externalTag, _): - return .external - case (Header.structTag, _): - return .struct - case (Header.classTag, _): - return .class - case (Header.computedTag, _): - return .computed - case (Header.optionalTag, Header.optionalChainPayload): - return .optionalChain - case (Header.optionalTag, Header.optionalWrapPayload): - return .optionalWrap - case (Header.optionalTag, Header.optionalForcePayload): - return .optionalForce - default: - _internalInvariantFailure("invalid header") - } - } // The component header is 4 bytes, but may be followed by an aligned // pointer field for some kinds of component, forcing padding. @@ -1185,12 +1191,6 @@ internal struct RawKeyPathComponent { } } - init(discriminator: UInt32, payload: UInt32) { - _value = 0 - self.discriminator = discriminator - self.payload = payload - } - init(optionalForce: ()) { self.init(discriminator: Header.optionalTag, payload: Header.optionalForcePayload) @@ -1735,6 +1735,23 @@ internal struct KeyPathBuffer { internal var trivial: Bool internal var hasReferencePrefix: Bool + internal init(base: UnsafeRawPointer) { + let header = base.load(as: Header.self) + data = UnsafeRawBufferPointer( + start: base + MemoryLayout.size, + count: header.size) + trivial = header.trivial + hasReferencePrefix = header.hasReferencePrefix + } + + internal init(partialData: UnsafeRawBufferPointer, + trivial: Bool = false, + hasReferencePrefix: Bool = false) { + self.data = partialData + self.trivial = trivial + self.hasReferencePrefix = hasReferencePrefix + } + internal var mutableData: UnsafeMutableRawBufferPointer { return UnsafeMutableRawBufferPointer(mutating: data) } @@ -1775,7 +1792,14 @@ internal struct KeyPathBuffer { internal struct Header { internal var _value: UInt32 - + + internal init(size: Int, trivial: Bool, hasReferencePrefix: Bool) { + _internalInvariant(size <= Int(Header.sizeMask), "key path too big") + _value = UInt32(size) + | (trivial ? Header.trivialFlag : 0) + | (hasReferencePrefix ? Header.hasReferencePrefixFlag : 0) + } + internal static var sizeMask: UInt32 { return _SwiftKeyPathBufferHeader_SizeMask } @@ -1789,13 +1813,6 @@ internal struct KeyPathBuffer { return _SwiftKeyPathBufferHeader_HasReferencePrefixFlag } - internal init(size: Int, trivial: Bool, hasReferencePrefix: Bool) { - _internalInvariant(size <= Int(Header.sizeMask), "key path too big") - _value = UInt32(size) - | (trivial ? Header.trivialFlag : 0) - | (hasReferencePrefix ? Header.hasReferencePrefixFlag : 0) - } - internal var size: Int { return Int(_value & Header.sizeMask) } internal var trivial: Bool { return _value & Header.trivialFlag != 0 } internal var hasReferencePrefix: Bool { @@ -1823,23 +1840,6 @@ internal struct KeyPathBuffer { } } - internal init(base: UnsafeRawPointer) { - let header = base.load(as: Header.self) - data = UnsafeRawBufferPointer( - start: base + MemoryLayout.size, - count: header.size) - trivial = header.trivial - hasReferencePrefix = header.hasReferencePrefix - } - - internal init(partialData: UnsafeRawBufferPointer, - trivial: Bool = false, - hasReferencePrefix: Bool = false) { - self.data = partialData - self.trivial = trivial - self.hasReferencePrefix = hasReferencePrefix - } - internal func destroy() { // Short-circuit if nothing in the object requires destruction. if trivial { return } diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift index 3a953e12e7c5b..2fe1a083f2879 100644 --- a/stdlib/public/core/Mirror.swift +++ b/stdlib/public/core/Mirror.swift @@ -40,68 +40,21 @@ /// To customize the mirror representation of a custom type, add conformance to /// the `CustomReflectable` protocol. public struct Mirror { - /// Representation of descendant classes that don't override - /// `customMirror`. - /// - /// Note that the effect of this setting goes no deeper than the - /// nearest descendant class that overrides `customMirror`, which - /// in turn can determine representation of *its* descendants. - internal enum _DefaultDescendantRepresentation { - /// Generate a default mirror for descendant classes that don't - /// override `customMirror`. - /// - /// This case is the default. - case generated - - /// Suppress the representation of descendant classes that don't - /// override `customMirror`. - /// - /// This option may be useful at the root of a class cluster, where - /// implementation details of descendants should generally not be - /// visible to clients. - case suppressed - } - - /// The representation to use for ancestor classes. + /// The static type of the subject being reflected. /// - /// A class that conforms to the `CustomReflectable` protocol can control how - /// its mirror represents ancestor classes by initializing the mirror - /// with an `AncestorRepresentation`. This setting has no effect on mirrors - /// reflecting value type instances. - public enum AncestorRepresentation { + /// This type may differ from the subject's dynamic type when this mirror + /// is the `superclassMirror` of another mirror. + public let subjectType: Any.Type - /// Generates a default mirror for all ancestor classes. - /// - /// This case is the default when initializing a `Mirror` instance. - /// - /// When you use this option, a subclass's mirror generates default mirrors - /// even for ancestor classes that conform to the `CustomReflectable` - /// protocol. To avoid dropping the customization provided by ancestor - /// classes, an override of `customMirror` should pass - /// `.customized({ super.customMirror })` as `ancestorRepresentation` when - /// initializing its mirror. - case generated + /// A collection of `Child` elements describing the structure of the + /// reflected subject. + public let children: Children - /// Uses the nearest ancestor's implementation of `customMirror` to create - /// a mirror for that ancestor. - /// - /// Other classes derived from such an ancestor are given a default mirror. - /// The payload for this option should always be `{ super.customMirror }`: - /// - /// var customMirror: Mirror { - /// return Mirror( - /// self, - /// children: ["someProperty": self.someProperty], - /// ancestorRepresentation: .customized({ super.customMirror })) // <== - /// } - case customized(() -> Mirror) + /// A suggested display style for the reflected subject. + public let displayStyle: DisplayStyle? - /// Suppresses the representation of all ancestor classes. - /// - /// In a mirror created with this ancestor representation, the - /// `superclassMirror` property is `nil`. - case suppressed - } + internal let _makeSuperclassMirror: () -> Mirror? + internal let _defaultDescendantRepresentation: _DefaultDescendantRepresentation /// Creates a mirror that reflects on the given instance. /// @@ -122,73 +75,6 @@ public struct Mirror { } } - /// An element of the reflected instance's structure. - /// - /// When the `label` component in not `nil`, it may represent the name of a - /// stored property or an active `enum` case. If you pass strings to the - /// `descendant(_:_:)` method, labels are used for lookup. - public typealias Child = (label: String?, value: Any) - - /// The type used to represent substructure. - /// - /// When working with a mirror that reflects a bidirectional or random access - /// collection, you may find it useful to "upgrade" instances of this type - /// to `AnyBidirectionalCollection` or `AnyRandomAccessCollection`. For - /// example, to display the last twenty children of a mirror if they can be - /// accessed efficiently, you write the following code: - /// - /// if let b = AnyBidirectionalCollection(someMirror.children) { - /// for element in b.suffix(20) { - /// print(element) - /// } - /// } - public typealias Children = AnyCollection - - /// A suggestion of how a mirror's subject is to be interpreted. - /// - /// Playgrounds and the debugger will show a representation similar - /// to the one used for instances of the kind indicated by the - /// `DisplayStyle` case name when the mirror is used for display. - public enum DisplayStyle: Sendable { - case `struct`, `class`, `enum`, tuple, optional, collection - case dictionary, `set` - } - - internal static func _noSuperclassMirror() -> Mirror? { return nil } - - @_semantics("optimize.sil.specialize.generic.never") - @inline(never) - internal static func _superclassIterator( - _ subject: Subject, _ ancestorRepresentation: AncestorRepresentation - ) -> () -> Mirror? { - - if let subjectClass = Subject.self as? AnyClass, - let superclass = _getSuperclass(subjectClass) { - - switch ancestorRepresentation { - case .generated: - return { - Mirror(internalReflecting: subject, subjectType: superclass) - } - case .customized(let makeAncestor): - return { - let ancestor = makeAncestor() - if superclass == ancestor.subjectType - || ancestor._defaultDescendantRepresentation == .suppressed { - return ancestor - } else { - return Mirror(internalReflecting: subject, - subjectType: superclass, - customAncestor: ancestor) - } - } - case .suppressed: - break - } - } - return Mirror._noSuperclassMirror - } - /// Creates a mirror representing the given subject with a specified /// structure. /// @@ -224,7 +110,7 @@ public struct Mirror { self.subjectType = Subject.self self._makeSuperclassMirror = Mirror._superclassIterator( subject, ancestorRepresentation) - + self.children = Children(children) self.displayStyle = displayStyle self._defaultDescendantRepresentation @@ -267,7 +153,7 @@ public struct Mirror { self.subjectType = Subject.self self._makeSuperclassMirror = Mirror._superclassIterator( subject, ancestorRepresentation) - + let lazyChildren = unlabeledChildren.lazy.map { Child(label: nil, value: $0) } self.children = Children(lazyChildren) @@ -315,7 +201,7 @@ public struct Mirror { self.subjectType = Subject.self self._makeSuperclassMirror = Mirror._superclassIterator( subject, ancestorRepresentation) - + let lazyChildren = children.lazy.map { Child(label: $0.0, value: $0.1) } self.children = Children(lazyChildren) @@ -324,26 +210,142 @@ public struct Mirror { = subject is CustomLeafReflectable ? .suppressed : .generated } - /// The static type of the subject being reflected. + /// A mirror of the subject's superclass, if one exists. + public var superclassMirror: Mirror? { + return _makeSuperclassMirror() + } +} + +extension Mirror { + /// Representation of descendant classes that don't override + /// `customMirror`. /// - /// This type may differ from the subject's dynamic type when this mirror - /// is the `superclassMirror` of another mirror. - public let subjectType: Any.Type + /// Note that the effect of this setting goes no deeper than the + /// nearest descendant class that overrides `customMirror`, which + /// in turn can determine representation of *its* descendants. + internal enum _DefaultDescendantRepresentation { + /// Generate a default mirror for descendant classes that don't + /// override `customMirror`. + /// + /// This case is the default. + case generated - /// A collection of `Child` elements describing the structure of the - /// reflected subject. - public let children: Children + /// Suppress the representation of descendant classes that don't + /// override `customMirror`. + /// + /// This option may be useful at the root of a class cluster, where + /// implementation details of descendants should generally not be + /// visible to clients. + case suppressed + } - /// A suggested display style for the reflected subject. - public let displayStyle: DisplayStyle? + /// The representation to use for ancestor classes. + /// + /// A class that conforms to the `CustomReflectable` protocol can control how + /// its mirror represents ancestor classes by initializing the mirror + /// with an `AncestorRepresentation`. This setting has no effect on mirrors + /// reflecting value type instances. + public enum AncestorRepresentation { - /// A mirror of the subject's superclass, if one exists. - public var superclassMirror: Mirror? { - return _makeSuperclassMirror() + /// Generates a default mirror for all ancestor classes. + /// + /// This case is the default when initializing a `Mirror` instance. + /// + /// When you use this option, a subclass's mirror generates default mirrors + /// even for ancestor classes that conform to the `CustomReflectable` + /// protocol. To avoid dropping the customization provided by ancestor + /// classes, an override of `customMirror` should pass + /// `.customized({ super.customMirror })` as `ancestorRepresentation` when + /// initializing its mirror. + case generated + + /// Uses the nearest ancestor's implementation of `customMirror` to create + /// a mirror for that ancestor. + /// + /// Other classes derived from such an ancestor are given a default mirror. + /// The payload for this option should always be `{ super.customMirror }`: + /// + /// var customMirror: Mirror { + /// return Mirror( + /// self, + /// children: ["someProperty": self.someProperty], + /// ancestorRepresentation: .customized({ super.customMirror })) // <== + /// } + case customized(() -> Mirror) + + /// Suppresses the representation of all ancestor classes. + /// + /// In a mirror created with this ancestor representation, the + /// `superclassMirror` property is `nil`. + case suppressed } - internal let _makeSuperclassMirror: () -> Mirror? - internal let _defaultDescendantRepresentation: _DefaultDescendantRepresentation + /// An element of the reflected instance's structure. + /// + /// When the `label` component in not `nil`, it may represent the name of a + /// stored property or an active `enum` case. If you pass strings to the + /// `descendant(_:_:)` method, labels are used for lookup. + public typealias Child = (label: String?, value: Any) + + /// The type used to represent substructure. + /// + /// When working with a mirror that reflects a bidirectional or random access + /// collection, you may find it useful to "upgrade" instances of this type + /// to `AnyBidirectionalCollection` or `AnyRandomAccessCollection`. For + /// example, to display the last twenty children of a mirror if they can be + /// accessed efficiently, you write the following code: + /// + /// if let b = AnyBidirectionalCollection(someMirror.children) { + /// for element in b.suffix(20) { + /// print(element) + /// } + /// } + public typealias Children = AnyCollection + + /// A suggestion of how a mirror's subject is to be interpreted. + /// + /// Playgrounds and the debugger will show a representation similar + /// to the one used for instances of the kind indicated by the + /// `DisplayStyle` case name when the mirror is used for display. + public enum DisplayStyle: Sendable { + case `struct`, `class`, `enum`, tuple, optional, collection + case dictionary, `set` + } + + internal static func _noSuperclassMirror() -> Mirror? { return nil } + + @_semantics("optimize.sil.specialize.generic.never") + @inline(never) + internal static func _superclassIterator( + _ subject: Subject, _ ancestorRepresentation: AncestorRepresentation + ) -> () -> Mirror? { + + if let subjectClass = Subject.self as? AnyClass, + let superclass = _getSuperclass(subjectClass) { + + switch ancestorRepresentation { + case .generated: + return { + Mirror(internalReflecting: subject, subjectType: superclass) + } + case .customized(let makeAncestor): + return { + let ancestor = makeAncestor() + if superclass == ancestor.subjectType + || ancestor._defaultDescendantRepresentation == .suppressed { + return ancestor + } else { + return Mirror(internalReflecting: subject, + subjectType: superclass, + customAncestor: ancestor) + } + } + case .suppressed: + break + } + } + return Mirror._noSuperclassMirror + } } /// A type that explicitly supplies its own mirror. diff --git a/stdlib/public/core/OutputStream.swift b/stdlib/public/core/OutputStream.swift index c5d357f8c6488..db4387a7b92ae 100644 --- a/stdlib/public/core/OutputStream.swift +++ b/stdlib/public/core/OutputStream.swift @@ -620,19 +620,16 @@ extension Unicode.Scalar: TextOutputStreamable { /// A hook for playgrounds to print through. public var _playgroundPrintHook: ((String) -> Void)? = nil -internal struct _TeeStream< - L: TextOutputStream, - R: TextOutputStream ->: TextOutputStream { +internal struct _TeeStream + : TextOutputStream +{ + internal var left: L + internal var right: R internal init(left: L, right: R) { self.left = left self.right = right } - - internal var left: L - internal var right: R - /// Append the given `string` to this stream. internal mutating func write(_ string: String) { left.write(string); right.write(string) diff --git a/stdlib/public/core/PrefixWhile.swift b/stdlib/public/core/PrefixWhile.swift index 7137242f7c4e1..02c824d089996 100644 --- a/stdlib/public/core/PrefixWhile.swift +++ b/stdlib/public/core/PrefixWhile.swift @@ -23,17 +23,17 @@ @frozen // lazy-performance public struct LazyPrefixWhileSequence { public typealias Element = Base.Element - - @inlinable // lazy-performance - internal init(_base: Base, predicate: @escaping (Element) -> Bool) { - self._base = _base - self._predicate = predicate - } @usableFromInline // lazy-performance internal var _base: Base @usableFromInline // lazy-performance internal let _predicate: (Element) -> Bool + + @inlinable // lazy-performance + internal init(_base: Base, predicate: @escaping (Element) -> Bool) { + self._base = _base + self._predicate = predicate + } } diff --git a/stdlib/public/core/Repeat.swift b/stdlib/public/core/Repeat.swift index c2101a72000e7..a86475b808f50 100644 --- a/stdlib/public/core/Repeat.swift +++ b/stdlib/public/core/Repeat.swift @@ -32,6 +32,15 @@ public struct Repeated { /// The value of every element in this collection. public let repeatedValue: Element + + /// Creates an instance that contains `count` elements having the + /// value `repeatedValue`. + @inlinable // trivial-implementation + internal init(_repeating repeatedValue: Element, count: Int) { + _precondition(count >= 0, "Repetition count should be non-negative") + self.count = count + self.repeatedValue = repeatedValue + } } extension Repeated: RandomAccessCollection { @@ -43,15 +52,6 @@ extension Repeated: RandomAccessCollection { /// end" position that's not valid for use as a subscript. public typealias Index = Int - /// Creates an instance that contains `count` elements having the - /// value `repeatedValue`. - @inlinable // trivial-implementation - internal init(_repeating repeatedValue: Element, count: Int) { - _precondition(count >= 0, "Repetition count should be non-negative") - self.count = count - self.repeatedValue = repeatedValue - } - /// The position of the first element in a nonempty collection. /// /// In a `Repeated` collection, `startIndex` is always equal to zero. If the diff --git a/stdlib/public/core/Runtime.swift b/stdlib/public/core/Runtime.swift index 7df18bd78a232..4a4c2ebfc7eb1 100644 --- a/stdlib/public/core/Runtime.swift +++ b/stdlib/public/core/Runtime.swift @@ -163,8 +163,6 @@ func _stdlib_atomicLoadARCRef( /// A 32 byte buffer. internal struct _Buffer32 { - internal init() {} - internal var _x0: UInt8 = 0 internal var _x1: UInt8 = 0 internal var _x2: UInt8 = 0 @@ -198,6 +196,8 @@ internal struct _Buffer32 { internal var _x30: UInt8 = 0 internal var _x31: UInt8 = 0 + internal init() {} + internal mutating func withBytes( _ body: (UnsafeMutablePointer) throws -> Result ) rethrows -> Result { @@ -209,8 +209,6 @@ internal struct _Buffer32 { /// A 72 byte buffer. internal struct _Buffer72 { - internal init() {} - internal var _x0: UInt8 = 0 internal var _x1: UInt8 = 0 internal var _x2: UInt8 = 0 @@ -284,6 +282,8 @@ internal struct _Buffer72 { internal var _x70: UInt8 = 0 internal var _x71: UInt8 = 0 + internal init() {} + internal mutating func withBytes( _ body: (UnsafeMutablePointer) throws -> Result ) rethrows -> Result { diff --git a/stdlib/public/core/SIMDVector.swift b/stdlib/public/core/SIMDVector.swift index 630eb41b7504e..a8b8291428b25 100644 --- a/stdlib/public/core/SIMDVector.swift +++ b/stdlib/public/core/SIMDVector.swift @@ -662,17 +662,17 @@ public struct SIMDMask: SIMD public typealias MaskStorage = Storage public typealias Scalar = Bool - - @_transparent - public var scalarCount: Int { - return _storage.scalarCount - } - + @_transparent public init() { _storage = Storage() } - + + @_transparent + public var scalarCount: Int { + return _storage.scalarCount + } + @_transparent public init(_ _storage: Storage) { self._storage = _storage diff --git a/stdlib/public/core/StaticString.swift b/stdlib/public/core/StaticString.swift index ac114c755a26f..0ef6c510fdced 100644 --- a/stdlib/public/core/StaticString.swift +++ b/stdlib/public/core/StaticString.swift @@ -91,6 +91,39 @@ public struct StaticString: Sendable { @usableFromInline internal var _flags: Builtin.Int8 + /// Creates an empty static string. + @_transparent + public init() { + self = "" + } + + @usableFromInline @_transparent + internal init( + _start: Builtin.RawPointer, + utf8CodeUnitCount: Builtin.Word, + isASCII: Builtin.Int1 + ) { + // We don't go through UnsafePointer here to make things simpler for alias + // analysis. A higher-level algorithm may be trying to make sure an + // unrelated buffer is not accessed or freed. + self._startPtrOrData = Builtin.ptrtoint_Word(_start) + self._utf8CodeUnitCount = utf8CodeUnitCount + self._flags = Bool(isASCII) + ? (0x2 as UInt8)._value + : (0x0 as UInt8)._value + } + + @usableFromInline @_transparent + internal init( + unicodeScalar: Builtin.Int32 + ) { + self._startPtrOrData = UInt(UInt32(unicodeScalar))._builtinWordValue + self._utf8CodeUnitCount = 0._builtinWordValue + self._flags = Unicode.Scalar(_builtinUnicodeScalarLiteral: unicodeScalar).isASCII + ? (0x3 as UInt8)._value + : (0x1 as UInt8)._value + } + /// A pointer to a null-terminated sequence of UTF-8 code units. /// /// - Important: Accessing this property when `hasPointerRepresentation` is @@ -175,39 +208,6 @@ public struct StaticString: Sendable { return unicodeScalar.withUTF8CodeUnits { body($0) } } } - - /// Creates an empty static string. - @_transparent - public init() { - self = "" - } - - @usableFromInline @_transparent - internal init( - _start: Builtin.RawPointer, - utf8CodeUnitCount: Builtin.Word, - isASCII: Builtin.Int1 - ) { - // We don't go through UnsafePointer here to make things simpler for alias - // analysis. A higher-level algorithm may be trying to make sure an - // unrelated buffer is not accessed or freed. - self._startPtrOrData = Builtin.ptrtoint_Word(_start) - self._utf8CodeUnitCount = utf8CodeUnitCount - self._flags = Bool(isASCII) - ? (0x2 as UInt8)._value - : (0x0 as UInt8)._value - } - - @usableFromInline @_transparent - internal init( - unicodeScalar: Builtin.Int32 - ) { - self._startPtrOrData = UInt(UInt32(unicodeScalar))._builtinWordValue - self._utf8CodeUnitCount = 0._builtinWordValue - self._flags = Unicode.Scalar(_builtinUnicodeScalarLiteral: unicodeScalar).isASCII - ? (0x3 as UInt8)._value - : (0x1 as UInt8)._value - } } extension StaticString: _ExpressibleByBuiltinUnicodeScalarLiteral { diff --git a/stdlib/public/core/StringSwitch.swift b/stdlib/public/core/StringSwitch.swift index ed70e9fd7de00..b2874ac8a346a 100644 --- a/stdlib/public/core/StringSwitch.swift +++ b/stdlib/public/core/StringSwitch.swift @@ -42,6 +42,9 @@ struct _OpaqueStringSwitchCache { internal typealias _StringSwitchCache = Dictionary internal struct _StringSwitchContext { + internal let cases: [StaticString] + internal let cachePtr: UnsafeMutablePointer<_StringSwitchCache> + internal init( cases: [StaticString], cachePtr: UnsafeMutablePointer<_StringSwitchCache> @@ -49,9 +52,6 @@ internal struct _StringSwitchContext { self.cases = cases self.cachePtr = cachePtr } - - internal let cases: [StaticString] - internal let cachePtr: UnsafeMutablePointer<_StringSwitchCache> } /// The compiler intrinsic which is called to lookup a string in a table diff --git a/stdlib/public/core/Substring.swift b/stdlib/public/core/Substring.swift index d0ae836ffea88..16bb727930766 100644 --- a/stdlib/public/core/Substring.swift +++ b/stdlib/public/core/Substring.swift @@ -334,6 +334,14 @@ extension Substring { public struct UTF8View: Sendable { @usableFromInline internal var _slice: Slice + + /// Creates an instance that slices `base` at `_bounds`. + @inlinable + internal init(_ base: String.UTF8View, _bounds: Range) { + _slice = Slice( + base: String(base._guts).utf8, + bounds: _bounds) + } } } @@ -343,14 +351,6 @@ extension Substring.UTF8View: BidirectionalCollection { public typealias Element = String.UTF8View.Element public typealias SubSequence = Substring.UTF8View - /// Creates an instance that slices `base` at `_bounds`. - @inlinable - internal init(_ base: String.UTF8View, _bounds: Range) { - _slice = Slice( - base: String(base._guts).utf8, - bounds: _bounds) - } - // // Plumb slice operations through // @@ -471,6 +471,14 @@ extension Substring { public struct UTF16View: Sendable { @usableFromInline internal var _slice: Slice + + /// Creates an instance that slices `base` at `_bounds`. + @inlinable + internal init(_ base: String.UTF16View, _bounds: Range) { + _slice = Slice( + base: String(base._guts).utf16, + bounds: _bounds) + } } } @@ -480,14 +488,6 @@ extension Substring.UTF16View: BidirectionalCollection { public typealias Element = String.UTF16View.Element public typealias SubSequence = Substring.UTF16View - /// Creates an instance that slices `base` at `_bounds`. - @inlinable - internal init(_ base: String.UTF16View, _bounds: Range) { - _slice = Slice( - base: String(base._guts).utf16, - bounds: _bounds) - } - // // Plumb slice operations through // @@ -597,6 +597,14 @@ extension Substring { public struct UnicodeScalarView: Sendable { @usableFromInline internal var _slice: Slice + + /// Creates an instance that slices `base` at `_bounds`. + @inlinable + internal init(_ base: String.UnicodeScalarView, _bounds: Range) { + _slice = Slice( + base: String(base._guts).unicodeScalars, + bounds: _bounds) + } } } @@ -606,14 +614,6 @@ extension Substring.UnicodeScalarView: BidirectionalCollection { public typealias Element = String.UnicodeScalarView.Element public typealias SubSequence = Substring.UnicodeScalarView - /// Creates an instance that slices `base` at `_bounds`. - @inlinable - internal init(_ base: String.UnicodeScalarView, _bounds: Range) { - _slice = Slice( - base: String(base._guts).unicodeScalars, - bounds: _bounds) - } - // // Plumb slice operations through // diff --git a/stdlib/public/core/UIntBuffer.swift b/stdlib/public/core/UIntBuffer.swift index cbfdcc8663096..434d4f5387d8b 100644 --- a/stdlib/public/core/UIntBuffer.swift +++ b/stdlib/public/core/UIntBuffer.swift @@ -37,9 +37,11 @@ public struct _UIntBuffer { extension _UIntBuffer: Sequence { public typealias SubSequence = Slice<_UIntBuffer> - + @frozen public struct Iterator: IteratorProtocol, Sequence { + public var _impl: _UIntBuffer + @inlinable @inline(__always) public init(_ x: _UIntBuffer) { _impl = x } @@ -54,8 +56,6 @@ extension _UIntBuffer: Sequence { } return Element(truncatingIfNeeded: _impl._storage) } - public - var _impl: _UIntBuffer } @inlinable diff --git a/stdlib/public/core/UTF16.swift b/stdlib/public/core/UTF16.swift index 3215066745208..c2f263f82e961 100644 --- a/stdlib/public/core/UTF16.swift +++ b/stdlib/public/core/UTF16.swift @@ -368,21 +368,25 @@ extension Unicode.UTF16: Unicode.Encoding { } return encode(FromEncoding.decode(content)) } - + @frozen public struct ForwardParser: Sendable { public typealias _Buffer = _UIntBuffer + + public var _buffer: _Buffer + @inlinable public init() { _buffer = _Buffer() } - public var _buffer: _Buffer } - + @frozen public struct ReverseParser: Sendable { public typealias _Buffer = _UIntBuffer + + public var _buffer: _Buffer + @inlinable public init() { _buffer = _Buffer() } - public var _buffer: _Buffer } } diff --git a/stdlib/public/core/UTF8.swift b/stdlib/public/core/UTF8.swift index ab026fbe2039e..be9871cf3b149 100644 --- a/stdlib/public/core/UTF8.swift +++ b/stdlib/public/core/UTF8.swift @@ -164,19 +164,23 @@ extension Unicode.UTF8: _UnicodeEncoding { @frozen public struct ForwardParser: Sendable { public typealias _Buffer = _UIntBuffer + + public var _buffer: _Buffer + @inline(__always) @inlinable public init() { _buffer = _Buffer() } - public var _buffer: _Buffer } @frozen public struct ReverseParser: Sendable { public typealias _Buffer = _UIntBuffer + + public var _buffer: _Buffer + @inline(__always) @inlinable public init() { _buffer = _Buffer() } - public var _buffer: _Buffer } } diff --git a/stdlib/public/core/UnfoldSequence.swift b/stdlib/public/core/UnfoldSequence.swift index 4904ee71e8998..77ae4d0373e40 100644 --- a/stdlib/public/core/UnfoldSequence.swift +++ b/stdlib/public/core/UnfoldSequence.swift @@ -102,6 +102,13 @@ public typealias UnfoldFirstSequence = UnfoldSequence /// `sequence(first:next:)` and `sequence(state:next:)`. @frozen // generic-performance public struct UnfoldSequence: Sequence, IteratorProtocol { + @usableFromInline // generic-performance + internal var _state: State + @usableFromInline // generic-performance + internal let _next: (inout State) -> Element? + @usableFromInline // generic-performance + internal var _done = false + @inlinable // generic-performance public mutating func next() -> Element? { guard !_done else { return nil } @@ -118,11 +125,4 @@ public struct UnfoldSequence: Sequence, IteratorProtocol { self._state = _state self._next = _next } - - @usableFromInline // generic-performance - internal var _state: State - @usableFromInline // generic-performance - internal let _next: (inout State) -> Element? - @usableFromInline // generic-performance - internal var _done = false } diff --git a/stdlib/public/core/UnicodeScalar.swift b/stdlib/public/core/UnicodeScalar.swift index 22dc501fedb1b..0c0175bd7ea7e 100644 --- a/stdlib/public/core/UnicodeScalar.swift +++ b/stdlib/public/core/UnicodeScalar.swift @@ -34,13 +34,13 @@ extension Unicode { /// // Prints "✈︎" @frozen public struct Scalar: Sendable { + @usableFromInline + internal var _value: UInt32 + @inlinable internal init(_value: UInt32) { self._value = _value } - - @usableFromInline - internal var _value: UInt32 } } @@ -388,12 +388,13 @@ extension Unicode.Scalar: Comparable { extension Unicode.Scalar { @frozen public struct UTF16View: Sendable { + @usableFromInline + internal var value: Unicode.Scalar + @inlinable internal init(value: Unicode.Scalar) { self.value = value } - @usableFromInline - internal var value: Unicode.Scalar } @inlinable @@ -438,12 +439,13 @@ extension Unicode.Scalar { @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) @frozen public struct UTF8View: Sendable { + @usableFromInline + internal var value: Unicode.Scalar + @inlinable internal init(value: Unicode.Scalar) { self.value = value } - @usableFromInline - internal var value: Unicode.Scalar } @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb index a8282f87f973e..afbb64d96f383 100644 --- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb +++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb @@ -43,6 +43,68 @@ public struct Unsafe${Mutable}BufferPointer { /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, /// a buffer can have a `count` of zero even with a non-`nil` base address. public let count: Int + + // This works around _debugPrecondition() impacting the performance of + // optimized code. (rdar://72246338) + @_alwaysEmitIntoClient + internal init( + @_nonEphemeral _uncheckedStart start: Unsafe${Mutable}Pointer?, + count: Int + ) { + _position = start + self.count = count + } + + /// Creates a new buffer pointer over the specified number of contiguous + /// instances beginning at the given pointer. + /// + /// - Parameters: + /// - start: A pointer to the start of the buffer, or `nil`. If `start` is + /// `nil`, `count` must be zero. However, `count` may be zero even for a + /// non-`nil` `start`. The pointer passed as `start` must be aligned to + /// `MemoryLayout.alignment`. + /// - count: The number of instances in the buffer. `count` must not be + /// negative. + @inlinable // unsafe-performance + public init( + @_nonEphemeral start: Unsafe${Mutable}Pointer?, count: Int + ) { + _debugPrecondition( + count >= 0, "Unsafe${Mutable}BufferPointer with negative count") + _debugPrecondition( + count == 0 || start != nil, + "Unsafe${Mutable}BufferPointer has a nil start and nonzero count") + self.init(_uncheckedStart: start, count: _assumeNonNegative(count)) + } + + @inlinable // unsafe-performance + public init(_empty: ()) { + _position = nil + count = 0 + } + +% if Mutable: + + /// Creates a mutable typed buffer pointer referencing the same memory as the + /// given immutable buffer pointer. + /// + /// - Parameter other: The immutable buffer pointer to convert. + @inlinable // unsafe-performance + public init(mutating other: UnsafeBufferPointer) { + _position = UnsafeMutablePointer(mutating: other._position) + count = other.count + } +% else: + /// Creates an immutable typed buffer pointer referencing the same memory as the + /// given mutable buffer pointer. + /// + /// - Parameter other: The mutable buffer pointer to convert. + @inlinable // unsafe-performance + public init(_ other: UnsafeMutableBufferPointer) { + _position = UnsafePointer(other._position) + count = other.count + } +% end } %if not mutable: @@ -394,57 +456,7 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle } extension Unsafe${Mutable}BufferPointer { - // This works around _debugPrecondition() impacting the performance of - // optimized code. (rdar://72246338) - @_alwaysEmitIntoClient - internal init( - @_nonEphemeral _uncheckedStart start: Unsafe${Mutable}Pointer?, - count: Int - ) { - _position = start - self.count = count - } - - /// Creates a new buffer pointer over the specified number of contiguous - /// instances beginning at the given pointer. - /// - /// - Parameters: - /// - start: A pointer to the start of the buffer, or `nil`. If `start` is - /// `nil`, `count` must be zero. However, `count` may be zero even for a - /// non-`nil` `start`. The pointer passed as `start` must be aligned to - /// `MemoryLayout.alignment`. - /// - count: The number of instances in the buffer. `count` must not be - /// negative. - @inlinable // unsafe-performance - public init( - @_nonEphemeral start: Unsafe${Mutable}Pointer?, count: Int - ) { - _debugPrecondition( - count >= 0, "Unsafe${Mutable}BufferPointer with negative count") - _debugPrecondition( - count == 0 || start != nil, - "Unsafe${Mutable}BufferPointer has a nil start and nonzero count") - self.init(_uncheckedStart: start, count: _assumeNonNegative(count)) - } - - @inlinable // unsafe-performance - public init(_empty: ()) { - _position = nil - count = 0 - } - % if Mutable: - - /// Creates a mutable typed buffer pointer referencing the same memory as the - /// given immutable buffer pointer. - /// - /// - Parameter other: The immutable buffer pointer to convert. - @inlinable // unsafe-performance - public init(mutating other: UnsafeBufferPointer) { - _position = UnsafeMutablePointer(mutating: other._position) - count = other.count - } - @inlinable @available(*, deprecated, renamed: "withContiguousMutableStorageIfAvailable") public mutating func _withUnsafeMutableBufferPointerIfSupported( @@ -474,16 +486,6 @@ extension Unsafe${Mutable}BufferPointer { % else: - /// Creates an immutable typed buffer pointer referencing the same memory as the - /// given mutable buffer pointer. - /// - /// - Parameter other: The mutable buffer pointer to convert. - @inlinable // unsafe-performance - public init(_ other: UnsafeMutableBufferPointer) { - _position = UnsafePointer(other._position) - count = other.count - } - @inlinable public func withContiguousStorageIfAvailable( _ body: (UnsafeBufferPointer) throws -> R diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb index c01039cb7b9a6..f0772ca8be7f5 100644 --- a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb +++ b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb @@ -96,6 +96,26 @@ public struct Unsafe${Mutable}RawBufferPointer { @usableFromInline internal let _position, _end: Unsafe${Mutable}RawPointer? + + /// Creates a buffer over the specified number of contiguous bytes starting + /// at the given pointer. + /// + /// - Parameters: + /// - start: The address of the memory that starts the buffer. If `starts` + /// is `nil`, `count` must be zero. However, `count` may be zero even + /// for a non-`nil` `start`. + /// - count: The number of bytes to include in the buffer. `count` must not + /// be negative. + @inlinable + public init( + @_nonEphemeral start: Unsafe${Mutable}RawPointer?, count: Int + ) { + _debugPrecondition(count >= 0, "${Self} with negative count") + _debugPrecondition(count == 0 || start != nil, + "${Self} has a nil start and nonzero count") + _position = start + _end = start.map { $0 + _assumeNonNegative(count) } + } } %if not mutable: @@ -455,26 +475,6 @@ extension Unsafe${Mutable}RawBufferPointer { } % end # mutable - /// Creates a buffer over the specified number of contiguous bytes starting - /// at the given pointer. - /// - /// - Parameters: - /// - start: The address of the memory that starts the buffer. If `starts` - /// is `nil`, `count` must be zero. However, `count` may be zero even - /// for a non-`nil` `start`. - /// - count: The number of bytes to include in the buffer. `count` must not - /// be negative. - @inlinable - public init( - @_nonEphemeral start: Unsafe${Mutable}RawPointer?, count: Int - ) { - _debugPrecondition(count >= 0, "${Self} with negative count") - _debugPrecondition(count == 0 || start != nil, - "${Self} has a nil start and nonzero count") - _position = start - _end = start.map { $0 + _assumeNonNegative(count) } - } - /// Creates a new buffer over the same memory as the given buffer. /// /// - Parameter bytes: The buffer to convert. diff --git a/stdlib/public/core/ValidUTF8Buffer.swift b/stdlib/public/core/ValidUTF8Buffer.swift index d97f5b8786447..38799a2a86aff 100644 --- a/stdlib/public/core/ValidUTF8Buffer.swift +++ b/stdlib/public/core/ValidUTF8Buffer.swift @@ -41,6 +41,9 @@ extension _ValidUTF8Buffer: Sequence { @frozen public struct Iterator: IteratorProtocol, Sequence { + @usableFromInline + internal var _biasedBits: UInt32 + @inlinable public init(_ x: _ValidUTF8Buffer) { _biasedBits = x._biasedBits } @@ -50,8 +53,6 @@ extension _ValidUTF8Buffer: Sequence { defer { _biasedBits >>= 8 } return Element(truncatingIfNeeded: _biasedBits) &- 1 } - @usableFromInline - internal var _biasedBits: UInt32 } @inlinable diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift index f2ccadd157df5..91429ac4dc8f2 100644 --- a/stdlib/public/core/VarArgs.swift +++ b/stdlib/public/core/VarArgs.swift @@ -444,9 +444,6 @@ final internal class __VaListBuilder { @frozen // c-abi @usableFromInline internal struct Header { - @inlinable // c-abi - internal init() {} - @usableFromInline // c-abi internal var gp_offset = CUnsignedInt(0) @usableFromInline // c-abi @@ -456,6 +453,9 @@ final internal class __VaListBuilder { internal var overflow_arg_area: UnsafeMutablePointer? @usableFromInline // c-abi internal var reg_save_area: UnsafeMutablePointer? + + @inlinable // c-abi + internal init() {} } #endif