From 30937785cdbf128257b5277162e2480b8ea298f2 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Fri, 16 Feb 2024 11:05:33 -0800 Subject: [PATCH 01/19] [stdlib] MemoryLayout: Add support for non-copyable type arguments [stdlib] MemoryLayout: Update Swift version numbers [stdlib] MemoryLayout: Actually hide legacy ABI --- stdlib/public/core/MemoryLayout.swift | 71 +++++++++++++++++++-- test/stdlib/Noncopyables/MemoryLayout.swift | 40 ++++++++++++ 2 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 test/stdlib/Noncopyables/MemoryLayout.swift diff --git a/stdlib/public/core/MemoryLayout.swift b/stdlib/public/core/MemoryLayout.swift index 164ffb227df38..dee1f30fa9a12 100644 --- a/stdlib/public/core/MemoryLayout.swift +++ b/stdlib/public/core/MemoryLayout.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2024 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 @@ -40,7 +40,9 @@ /// byteCount: count * MemoryLayout.stride, /// alignment: MemoryLayout.alignment) @frozen // namespace -public enum MemoryLayout { +public enum MemoryLayout {} + +extension MemoryLayout where T: ~Copyable { /// The contiguous memory footprint of `T`, in bytes. /// /// A type's size does not include any dynamically allocated or out of line @@ -50,6 +52,7 @@ public enum MemoryLayout { /// When allocating memory for multiple instances of `T` using an unsafe /// pointer, use a multiple of the type's stride instead of its size. @_transparent + @_alwaysEmitIntoClient public static var size: Int { return Int(Builtin.sizeof(T.self)) } @@ -62,6 +65,7 @@ public enum MemoryLayout { /// trades runtime performance for space efficiency. This value is always /// positive. @_transparent + @_alwaysEmitIntoClient public static var stride: Int { return Int(Builtin.strideof(T.self)) } @@ -71,6 +75,7 @@ public enum MemoryLayout { /// Use the `alignment` property for a type when allocating memory using an /// unsafe pointer. This value is always positive. @_transparent + @_alwaysEmitIntoClient public static var alignment: Int { return Int(Builtin.alignof(T.self)) } @@ -80,6 +85,29 @@ public enum MemoryLayout { extension MemoryLayout : _BitwiseCopyable {} extension MemoryLayout { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal static var size: Int { + return Int(Builtin.sizeof(T.self)) + } + + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal static var stride: Int { + return Int(Builtin.strideof(T.self)) + } + + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal static var alignment: Int { + return Int(Builtin.alignof(T.self)) + } +} + +extension MemoryLayout where T: ~Copyable { /// Returns the contiguous memory footprint of the given instance. /// /// The result does not include any dynamically allocated or out of line @@ -103,7 +131,8 @@ extension MemoryLayout { /// - Parameter value: A value representative of the type to describe. /// - Returns: The size, in bytes, of the given value's type. @_transparent - public static func size(ofValue value: T) -> Int { + @_alwaysEmitIntoClient + public static func size(ofValue value: borrowing T) -> Int { return MemoryLayout.size } @@ -131,7 +160,8 @@ extension MemoryLayout { /// - Parameter value: A value representative of the type to describe. /// - Returns: The stride, in bytes, of the given value's type. @_transparent - public static func stride(ofValue value: T) -> Int { + @_alwaysEmitIntoClient + public static func stride(ofValue value: borrowing T) -> Int { return MemoryLayout.stride } @@ -156,10 +186,36 @@ extension MemoryLayout { /// - Returns: The default memory alignment, in bytes, of the given value's /// type. This value is always positive. @_transparent - public static func alignment(ofValue value: T) -> Int { + @_alwaysEmitIntoClient + public static func alignment(ofValue value: borrowing T) -> Int { return MemoryLayout.alignment } +} +extension MemoryLayout { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal static func size(ofValue value: borrowing T) -> Int { + return MemoryLayout.size + } + + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal static func stride(ofValue value: borrowing T) -> Int { + return MemoryLayout.stride + } + + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal static func alignment(ofValue value: borrowing T) -> Int { + return MemoryLayout.alignment + } +} + +extension MemoryLayout { /// Returns the offset of an inline stored property within a type's in-memory /// representation. /// @@ -229,12 +285,15 @@ extension MemoryLayout { @_transparent @_unavailableInEmbedded public static func offset(of key: PartialKeyPath) -> Int? { + // FIXME(noncopyableGenerics): The new (implicit) `where T: Copyable` + // extension constraint currently changes the mangling of this from a + // standalone function to an extension method. return key._storedInlineOffset } } // Not-yet-public alignment conveniences -extension MemoryLayout { +extension MemoryLayout where T: ~Copyable { internal static var _alignmentMask: Int { return alignment - 1 } internal static func _roundingUpToAlignment(_ value: Int) -> Int { diff --git a/test/stdlib/Noncopyables/MemoryLayout.swift b/test/stdlib/Noncopyables/MemoryLayout.swift new file mode 100644 index 0000000000000..188ff728874db --- /dev/null +++ b/test/stdlib/Noncopyables/MemoryLayout.swift @@ -0,0 +1,40 @@ +// RUN: %empty-directory(%t) +// RUN: %target-run-simple-swift(-enable-experimental-feature NoncopyableGenerics) | %FileCheck %s +// REQUIRES: executable_test, noncopyable_generics + +struct A: ~Copyable { + let value: Int + + init(_ value: Int) { self.value = value } +} + +let expectedSize = MemoryLayout.size +let expectedStride = MemoryLayout.stride +let expectedAlignment = MemoryLayout.alignment + + +let actualSize1 = MemoryLayout.size +// CHECK: size: true +print("size: \(actualSize1 == expectedSize)") + +let actualStride1 = MemoryLayout.stride +// CHECK: stride: true +print("stride: \(actualStride1 == expectedStride)") + +let actualAlignment1 = MemoryLayout.alignment +// CHECK: alignment: true +print("alignment: \(actualAlignment1 == expectedAlignment)") + +let a = A(42) + +let actualSize2 = MemoryLayout.size(ofValue: a) +// CHECK: size(ofValue:): true +print("size(ofValue:): \(actualSize2 == expectedSize)") + +let actualStride2 = MemoryLayout.stride(ofValue: a) +// CHECK: stride(ofValue:): true +print("stride(ofValue:): \(actualStride2 == expectedStride)") + +let actualAlignment2 = MemoryLayout.alignment(ofValue: a) +// CHECK: alignment(ofValue:): true +print("alignment(ofValue:): \(actualAlignment2 == expectedAlignment)") From b3064f579d57771ded7ad2961b1eabca02959f33 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Fri, 16 Feb 2024 11:43:04 -0800 Subject: [PATCH 02/19] [stdlib] Unsafe[Mutable]Pointer: Add support for non-copyable Pointee types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [stdlib] Pull back @_aeic on pointer → integer conversions [stdlib] UnsafeMutablePointer.allocate: Fix thinko [stdlib] Disable support for noncopyable pointees on some pointer operations We have to temporarily pull back support for noncopyable pointees for UnsafeMutablePointer.initialize(to:), .moveInitialize, .moveUpdate, as the builtins they’re calling are no longer accepting such types. These will return following a builtin audit. [stdlib] Remove workarounds for certain builtins not supporting noncopyable use https://github.com/apple/swift/pull/71733 fixed this! [stdlib] Update FIXME [stdlib] UnsafePointer: Update Swift version numbers [stdlib] UnsafePointer: Actually hide legacy ABI [stdlib] Remove workaround for U[M]BP.withMemoryRebound --- stdlib/public/Cxx/UnsafeCxxIterators.swift | 33 +- .../Synchronization/AtomicPointers.swift | 9 +- stdlib/public/core/MigrationSupport.swift | 8 +- stdlib/public/core/Pointer.swift | 6 +- stdlib/public/core/UnsafePointer.swift | 392 +++++++++++++++--- stdlib/public/core/UnsafeRawPointer.swift | 33 +- stdlib/public/core/VarArgs.swift | 4 +- 7 files changed, 394 insertions(+), 91 deletions(-) diff --git a/stdlib/public/Cxx/UnsafeCxxIterators.swift b/stdlib/public/Cxx/UnsafeCxxIterators.swift index ee913710ab0c3..bdcd3b609f9b8 100644 --- a/stdlib/public/Cxx/UnsafeCxxIterators.swift +++ b/stdlib/public/Cxx/UnsafeCxxIterators.swift @@ -18,12 +18,13 @@ /// /// - SeeAlso: https://en.cppreference.com/w/cpp/named_req/InputIterator public protocol UnsafeCxxInputIterator: Equatable { - associatedtype Pointee + associatedtype Pointee: ~Copyable /// Returns the unwrapped result of C++ `operator*()`. /// /// Generally, Swift creates this property automatically for C++ types that /// define `operator*()`. + @_borrowed var pointee: Pointee { get } /// Returns an iterator pointing to the next item in the sequence. @@ -33,19 +34,23 @@ public protocol UnsafeCxxInputIterator: Equatable { func successor() -> Self } -extension UnsafePointer: UnsafeCxxInputIterator {} +extension UnsafePointer: UnsafeCxxInputIterator +where Pointee: ~Copyable {} -extension UnsafeMutablePointer: UnsafeCxxInputIterator {} +extension UnsafeMutablePointer: UnsafeCxxInputIterator +where Pointee: ~Copyable {} extension Optional: UnsafeCxxInputIterator where Wrapped: UnsafeCxxInputIterator { public typealias Pointee = Wrapped.Pointee @inlinable public var pointee: Pointee { - if let value = self { - return value.pointee + _read { + guard let value = self else { + fatalError("Could not dereference nullptr") + } + yield value.pointee } - fatalError("Could not dereference nullptr") } @inlinable @@ -58,10 +63,12 @@ extension Optional: UnsafeCxxInputIterator where Wrapped: UnsafeCxxInputIterator } public protocol UnsafeCxxMutableInputIterator: UnsafeCxxInputIterator { + @_borrowed override var pointee: Pointee { get set } } -extension UnsafeMutablePointer: UnsafeCxxMutableInputIterator {} +extension UnsafeMutablePointer: UnsafeCxxMutableInputIterator +where Pointee: ~Copyable {} /// Bridged C++ iterator that allows computing the distance between two of its /// instances, and advancing an instance by a given number of elements. @@ -77,10 +84,14 @@ public protocol UnsafeCxxRandomAccessIterator: UnsafeCxxInputIterator { static func +=(lhs: inout Self, rhs: Distance) } -extension UnsafePointer: UnsafeCxxRandomAccessIterator {} +extension UnsafePointer: UnsafeCxxRandomAccessIterator +where Pointee: ~Copyable {} -extension UnsafeMutablePointer: UnsafeCxxRandomAccessIterator {} +extension UnsafeMutablePointer: UnsafeCxxRandomAccessIterator +where Pointee: ~Copyable {} -public protocol UnsafeCxxMutableRandomAccessIterator: UnsafeCxxRandomAccessIterator, UnsafeCxxMutableInputIterator {} +public protocol UnsafeCxxMutableRandomAccessIterator: +UnsafeCxxRandomAccessIterator, UnsafeCxxMutableInputIterator {} -extension UnsafeMutablePointer: UnsafeCxxMutableRandomAccessIterator {} +extension UnsafeMutablePointer: UnsafeCxxMutableRandomAccessIterator +where Pointee: ~Copyable {} diff --git a/stdlib/public/Synchronization/AtomicPointers.swift b/stdlib/public/Synchronization/AtomicPointers.swift index 93e3a5855b8e5..6622de2f1188b 100644 --- a/stdlib/public/Synchronization/AtomicPointers.swift +++ b/stdlib/public/Synchronization/AtomicPointers.swift @@ -15,7 +15,7 @@ //===----------------------------------------------------------------------===// @available(SwiftStdlib 6.0, *) -extension UnsafePointer: AtomicRepresentable { +extension UnsafePointer: AtomicRepresentable where Pointee: ~Copyable { /// The storage representation type that `Self` encodes to and decodes from /// which is a suitable type when used in atomic operations. @available(SwiftStdlib 6.0, *) @@ -65,7 +65,7 @@ extension UnsafePointer: AtomicRepresentable { } @available(SwiftStdlib 6.0, *) -extension UnsafePointer: AtomicOptionalRepresentable { +extension UnsafePointer: AtomicOptionalRepresentable where Pointee: ~Copyable { /// The storage representation type that encodes to and decodes from /// `Optional` which is a suitable type when used in atomic operations /// on `Optional`. @@ -121,7 +121,7 @@ extension UnsafePointer: AtomicOptionalRepresentable { //===----------------------------------------------------------------------===// @available(SwiftStdlib 6.0, *) -extension UnsafeMutablePointer: AtomicRepresentable { +extension UnsafeMutablePointer: AtomicRepresentable where Pointee: ~Copyable { /// The storage representation type that `Self` encodes to and decodes from /// which is a suitable type when used in atomic operations. @available(SwiftStdlib 6.0, *) @@ -171,7 +171,8 @@ extension UnsafeMutablePointer: AtomicRepresentable { } @available(SwiftStdlib 6.0, *) -extension UnsafeMutablePointer: AtomicOptionalRepresentable { +extension UnsafeMutablePointer: AtomicOptionalRepresentable +where Pointee: ~Copyable { /// The storage representation type that encodes to and decodes from /// `Optional` which is a suitable type when used in atomic operations /// on `Optional`. diff --git a/stdlib/public/core/MigrationSupport.swift b/stdlib/public/core/MigrationSupport.swift index 93ceecafc50a2..c04ff068c989c 100644 --- a/stdlib/public/core/MigrationSupport.swift +++ b/stdlib/public/core/MigrationSupport.swift @@ -425,7 +425,9 @@ extension UnsafeMutableRawPointer: _CustomPlaygroundQuickLookable { } } -extension UnsafePointer: _CustomPlaygroundQuickLookable { +extension UnsafePointer: _CustomPlaygroundQuickLookable +where Pointee: ~Copyable // FIXME: Remove this (rdar://123262870) +{ private var summary: String { let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue)))) return ptrValue == 0 @@ -439,7 +441,9 @@ extension UnsafePointer: _CustomPlaygroundQuickLookable { } } -extension UnsafeMutablePointer: _CustomPlaygroundQuickLookable { +extension UnsafeMutablePointer: _CustomPlaygroundQuickLookable +where Pointee: ~Copyable // FIXME: Remove this (rdar://123262870) +{ private var summary: String { let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue)))) return ptrValue == 0 diff --git a/stdlib/public/core/Pointer.swift b/stdlib/public/core/Pointer.swift index 3798501404f60..3e4640ea56f20 100644 --- a/stdlib/public/core/Pointer.swift +++ b/stdlib/public/core/Pointer.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2024 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 @@ -30,8 +30,8 @@ public protocol _Pointer , _BitwiseCopyable { /// A type that represents the distance between two pointers. typealias Distance = Int - - associatedtype Pointee + + associatedtype Pointee: ~Copyable /// The underlying raw pointer value. var _rawValue: Builtin.RawPointer { get } diff --git a/stdlib/public/core/UnsafePointer.swift b/stdlib/public/core/UnsafePointer.swift index 6d6bbfe6c75af..d58ffe5823fd9 100644 --- a/stdlib/public/core/UnsafePointer.swift +++ b/stdlib/public/core/UnsafePointer.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2024 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 @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// -/// A pointer for accessing data of a -/// specific type. +/// A pointer for accessing data of a specific type. /// /// You use instances of the `UnsafePointer` type to access data of a /// specific type in memory. The type of data that a pointer can access is the @@ -205,7 +204,7 @@ /// let numberPointer = UnsafePointer(&number) /// // Accessing 'numberPointer' is undefined behavior. @frozen // unsafe-performance -public struct UnsafePointer: _Pointer { +public struct UnsafePointer: _Pointer, Copyable { /// A type that represents the distance between two pointers. public typealias Distance = Int @@ -214,16 +213,29 @@ public struct UnsafePointer: _Pointer { public let _rawValue: Builtin.RawPointer /// Creates an `UnsafePointer` from a builtin raw pointer. + @_alwaysEmitIntoClient @_transparent public init(_ _rawValue: Builtin.RawPointer) { self._rawValue = _rawValue } +} +extension UnsafePointer { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal init(_ _rawValue: Builtin.RawPointer) { + self._rawValue = _rawValue + } +} + +extension UnsafePointer where Pointee: ~Copyable { /// Deallocates the memory block previously allocated at this pointer. /// - /// This pointer must be a pointer to the start of a previously allocated memory - /// block. The memory must not be initialized or `Pointee` must be a trivial type. - @inlinable + /// This pointer must be a pointer to the start of a previously allocated + /// memory block. The memory must not be initialized or `Pointee` must be a + /// trivial type. + @_alwaysEmitIntoClient public func deallocate() { // Passing zero alignment to the runtime forces "aligned // deallocation". Since allocation via `UnsafeMutable[Raw][Buffer]Pointer` @@ -231,18 +243,75 @@ public struct UnsafePointer: _Pointer { // runtime's allocation and deallocation paths are compatible. Builtin.deallocRaw(_rawValue, (-1)._builtinWordValue, (0)._builtinWordValue) } +} +extension UnsafePointer { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal func deallocate() { + // Passing zero alignment to the runtime forces "aligned + // deallocation". Since allocation via `UnsafeMutable[Raw][Buffer]Pointer` + // always uses the "aligned allocation" path, this ensures that the + // runtime's allocation and deallocation paths are compatible. + Builtin.deallocRaw(_rawValue, (-1)._builtinWordValue, (0)._builtinWordValue) + } +} + +extension UnsafePointer where Pointee: ~Copyable { /// Accesses the instance referenced by this pointer. /// /// When reading from the `pointee` property, the instance referenced by /// this pointer must already be initialized. - @inlinable // unsafe-performance + @_alwaysEmitIntoClient public var pointee: Pointee { @_transparent unsafeAddress { return self } } +} + +extension UnsafePointer { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal var pointee: Pointee { + unsafeAddress { + return self + } + } +} + +extension UnsafePointer where Pointee: ~Copyable { + /// Accesses the pointee at the specified offset from this pointer. + /// + /// + /// For a pointer `p`, the memory at `p + i` must be initialized. + /// + /// - Parameter i: The offset from this pointer at which to access an + /// instance, measured in strides of the pointer's `Pointee` type. + @_alwaysEmitIntoClient + public subscript(i: Int) -> Pointee { + @_transparent + unsafeAddress { + return self + i + } + } +} +extension UnsafePointer { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal subscript(i: Int) -> Pointee { + @_transparent + unsafeAddress { + return self + i + } + } +} + +extension UnsafePointer where Pointee: ~Copyable { /// Executes the given closure while temporarily binding memory to /// the specified number of instances of type `T`. /// @@ -304,11 +373,11 @@ public struct UnsafePointer: _Pointer { /// the return value for the `withMemoryRebound(to:capacity:_:)` method. /// - pointer: The pointer temporarily bound to `T`. /// - Returns: The return value, if any, of the `body` closure parameter. - @inlinable @_alwaysEmitIntoClient // This custom silgen name is chosen to not interfere with the old ABI @_silgen_name("_swift_se0333_UnsafePointer_withMemoryRebound") - public func withMemoryRebound( + // TODO: Remove @_silgen_name once ~Copyable can be a thing above + public func withMemoryRebound( to type: T.Type, capacity count: Int, _ body: (_ pointer: UnsafePointer) throws -> Result @@ -327,12 +396,14 @@ public struct UnsafePointer: _Pointer { defer { Builtin.rebindMemory(_rawValue, binding) } return try body(.init(_rawValue)) } +} +extension UnsafePointer { // This unavailable implementation uses the expected mangled name // of `withMemoryRebound(to:capacity:_:)`, and provides // an entry point for any binary linked against the stdlib binary // for Swift 5.6 and older. - @available(*, unavailable) + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) @_silgen_name("$sSP17withMemoryRebound2to8capacity_qd_0_qd__m_Siqd_0_SPyqd__GKXEtKr0_lF") @usableFromInline internal func _legacy_se0333_withMemoryRebound( @@ -344,22 +415,9 @@ public struct UnsafePointer: _Pointer { defer { Builtin.rebindMemory(_rawValue, binding) } return try body(.init(_rawValue)) } +} - /// Accesses the pointee at the specified offset from this pointer. - /// - /// - /// For a pointer `p`, the memory at `p + i` must be initialized. - /// - /// - Parameter i: The offset from this pointer at which to access an - /// instance, measured in strides of the pointer's `Pointee` type. - @inlinable - public subscript(i: Int) -> Pointee { - @_transparent - unsafeAddress { - return self + i - } - } - +extension UnsafePointer { /// Obtain a pointer to the stored property referred to by a key path. /// /// If the key path represents a computed property, @@ -368,7 +426,6 @@ public struct UnsafePointer: _Pointer { /// - Parameter property: A `KeyPath` whose `Root` is `Pointee`. /// - Returns: A pointer to the stored property represented /// by the key path, or `nil`. - @inlinable @_alwaysEmitIntoClient @_unavailableInEmbedded public func pointer( @@ -382,7 +439,9 @@ public struct UnsafePointer: _Pointer { ) return .init(Builtin.gepRaw_Word(_rawValue, o._builtinWordValue)) } +} +extension UnsafePointer { @inlinable // unsafe-performance internal static var _max: UnsafePointer { return UnsafePointer( @@ -578,7 +637,7 @@ public struct UnsafePointer: _Pointer { /// let numberPointer = UnsafeMutablePointer(&number) /// // Accessing 'numberPointer' is undefined behavior. @frozen // unsafe-performance -public struct UnsafeMutablePointer: _Pointer { +public struct UnsafeMutablePointer: _Pointer, Copyable { /// A type that represents the distance between two pointers. public typealias Distance = Int @@ -587,6 +646,7 @@ public struct UnsafeMutablePointer: _Pointer { public let _rawValue: Builtin.RawPointer /// Creates an `UnsafeMutablePointer` from a builtin raw pointer. + @_alwaysEmitIntoClient @_transparent public init(_ _rawValue: Builtin.RawPointer) { self._rawValue = _rawValue @@ -596,6 +656,7 @@ public struct UnsafeMutablePointer: _Pointer { /// immutable pointer. /// /// - Parameter other: The immutable pointer to convert. + @_alwaysEmitIntoClient @_transparent public init(@_nonEphemeral mutating other: UnsafePointer) { self._rawValue = other._rawValue @@ -606,6 +667,7 @@ public struct UnsafeMutablePointer: _Pointer { /// /// - Parameter other: The immutable pointer to convert. If `other` is `nil`, /// the result is `nil`. + @_alwaysEmitIntoClient @_transparent public init?(@_nonEphemeral mutating other: UnsafePointer?) { guard let unwrapped = other else { return nil } @@ -616,6 +678,7 @@ public struct UnsafeMutablePointer: _Pointer { /// given mutable pointer. /// /// - Parameter other: The pointer to convert. + @_alwaysEmitIntoClient @_transparent public init(@_nonEphemeral _ other: UnsafeMutablePointer) { self._rawValue = other._rawValue @@ -626,13 +689,54 @@ public struct UnsafeMutablePointer: _Pointer { /// /// - Parameter other: The pointer to convert. If `other` is `nil`, the /// result is `nil`. + @_alwaysEmitIntoClient @_transparent public init?(@_nonEphemeral _ other: UnsafeMutablePointer?) { guard let unwrapped = other else { return nil } self.init(unwrapped) } - +} + +extension UnsafeMutablePointer { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal init(_ _rawValue: Builtin.RawPointer) { + self._rawValue = _rawValue + } + + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal init(@_nonEphemeral mutating other: UnsafePointer) { + self._rawValue = other._rawValue + } + + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal init?(@_nonEphemeral mutating other: UnsafePointer?) { + guard let unwrapped = other else { return nil } + self.init(mutating: unwrapped) + } + + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal init(@_nonEphemeral _ other: UnsafeMutablePointer) { + self._rawValue = other._rawValue + } + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal init?(@_nonEphemeral _ other: UnsafeMutablePointer?) { + guard let unwrapped = other else { return nil } + self.init(unwrapped) + } +} + +extension UnsafeMutablePointer where Pointee: ~Copyable { /// Allocates uninitialized memory for the specified number of instances of /// type `Pointee`. /// @@ -656,7 +760,7 @@ public struct UnsafeMutablePointer: _Pointer { /// /// - Parameter count: The amount of memory to allocate, counted in instances /// of `Pointee`. - @inlinable + @_alwaysEmitIntoClient public static func allocate(capacity count: Int) -> UnsafeMutablePointer { let size = MemoryLayout.stride * count @@ -679,12 +783,43 @@ public struct UnsafeMutablePointer: _Pointer { Builtin.bindMemory(rawPtr, count._builtinWordValue, Pointee.self) return UnsafeMutablePointer(rawPtr) } +} + +extension UnsafeMutablePointer { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal static func allocate( + capacity count: Int + ) -> UnsafeMutablePointer { + let size = MemoryLayout.stride * count + // For any alignment <= _minAllocationAlignment, force alignment = 0. + // This forces the runtime's "aligned" allocation path so that + // deallocation does not require the original alignment. + // + // The runtime guarantees: + // + // align == 0 || align > _minAllocationAlignment: + // Runtime uses "aligned allocation". + // + // 0 < align <= _minAllocationAlignment: + // Runtime may use either malloc or "aligned allocation". + var align = Builtin.alignof(Pointee.self) + if Int(align) <= _minAllocationAlignment() { + align = (0)._builtinWordValue + } + let rawPtr = Builtin.allocRaw(size._builtinWordValue, align) + Builtin.bindMemory(rawPtr, count._builtinWordValue, Pointee.self) + return UnsafeMutablePointer(rawPtr) + } +} +extension UnsafeMutablePointer where Pointee: ~Copyable { /// Deallocates the memory block previously allocated at this pointer. /// /// This pointer must be a pointer to the start of a previously allocated memory /// block. The memory must not be initialized or `Pointee` must be a trivial type. - @inlinable + @_alwaysEmitIntoClient public func deallocate() { // Passing zero alignment to the runtime forces "aligned // deallocation". Since allocation via `UnsafeMutable[Raw][Buffer]Pointer` @@ -692,7 +827,23 @@ public struct UnsafeMutablePointer: _Pointer { // runtime's allocation and deallocation paths are compatible. Builtin.deallocRaw(_rawValue, (-1)._builtinWordValue, (0)._builtinWordValue) } +} +extension UnsafeMutablePointer { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal func deallocate() { + // Passing zero alignment to the runtime forces "aligned + // deallocation". Since allocation via `UnsafeMutable[Raw][Buffer]Pointer` + // always uses the "aligned allocation" path, this ensures that the + // runtime's allocation and deallocation paths are compatible. + Builtin.deallocRaw(_rawValue, (-1)._builtinWordValue, (0)._builtinWordValue) + } +} + + +extension UnsafeMutablePointer where Pointee: ~Copyable { /// Reads or updates the instance referenced by this pointer. /// /// When reading from the `pointee` property, the instance referenced by this @@ -712,7 +863,22 @@ public struct UnsafeMutablePointer: _Pointer { return self } } +} +extension UnsafeMutablePointer { + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal var pointee: Pointee { + @_transparent unsafeAddress { + return UnsafePointer(self) + } + @_transparent nonmutating unsafeMutableAddress { + return self + } + } +} + +extension UnsafeMutablePointer { /// Initializes this pointer's memory with the specified number of /// consecutive copies of the given value. /// @@ -735,22 +901,34 @@ public struct UnsafeMutablePointer: _Pointer { Builtin.initialize(repeatedValue, (self + offset)._rawValue) } } - - /// Initializes this pointer's memory with a single instance of the given value. +} + +extension UnsafeMutablePointer where Pointee: ~Copyable { + /// Initializes this pointer's memory with a single instance of the given + /// value. /// /// The destination memory must be uninitialized or the pointer's `Pointee` - /// must be a trivial type. After a call to `initialize(to:)`, the - /// memory referenced by this pointer is initialized. Calling this method is - /// roughly equivalent to calling `initialize(repeating:count:)` with a - /// `count` of 1. + /// must be a trivial type. After a call to `initialize(to:)`, the memory + /// referenced by this pointer is initialized. Calling this method is roughly + /// equivalent to calling `initialize(repeating:count:)` with a `count` of 1. /// /// - Parameters: /// - value: The instance to initialize this pointer's pointee to. - @inlinable - public func initialize(to value: Pointee) { + @_alwaysEmitIntoClient + public func initialize(to value: consuming Pointee) { + Builtin.initialize(value, self._rawValue) + } +} + +extension UnsafeMutablePointer { + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal func initialize(to value: Pointee) { // Note: `value` was __shared! Builtin.initialize(value, self._rawValue) } +} +extension UnsafeMutablePointer where Pointee: ~Copyable { /// Retrieves and returns the referenced instance, returning the pointer's /// memory to an uninitialized state. /// @@ -767,11 +945,22 @@ public struct UnsafeMutablePointer: _Pointer { /// `move()`, the memory is uninitialized. /// /// - Returns: The instance referenced by this pointer. - @inlinable + @_alwaysEmitIntoClient public func move() -> Pointee { return Builtin.take(_rawValue) } +} +extension UnsafeMutablePointer { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal func move() -> Pointee { + return Builtin.take(_rawValue) + } +} + +extension UnsafeMutablePointer { /// Update this pointer's initialized memory with the specified number of /// consecutive copies of the given value. /// @@ -792,15 +981,17 @@ public struct UnsafeMutablePointer: _Pointer { self[i] = repeatedValue } } + - @inlinable @_alwaysEmitIntoClient @available(*, deprecated, renamed: "update(repeating:count:)") @_silgen_name("_swift_se0370_UnsafeMutablePointer_assign_repeating_count") public func assign(repeating repeatedValue: Pointee, count: Int) { update(repeating: repeatedValue, count: count) } +} +extension UnsafeMutablePointer { /// Update this pointer's initialized memory with the specified number of /// instances, copied from the given pointer's memory. /// @@ -851,7 +1042,9 @@ public struct UnsafeMutablePointer: _Pointer { public func assign(from source: UnsafePointer, count: Int) { update(from: source, count: count) } +} +extension UnsafeMutablePointer where Pointee: ~Copyable { /// Moves instances from initialized source memory into the uninitialized /// memory referenced by this pointer, leaving the source memory /// uninitialized and the memory referenced by this pointer initialized. @@ -870,7 +1063,7 @@ public struct UnsafeMutablePointer: _Pointer { /// referenced by `source` and this pointer may overlap. /// - count: The number of instances to move from `source` to this /// pointer's memory. `count` must not be negative. - @inlinable + @_alwaysEmitIntoClient public func moveInitialize( @_nonEphemeral from source: UnsafeMutablePointer, count: Int ) { @@ -897,7 +1090,41 @@ public struct UnsafeMutablePointer: _Pointer { // } } } +} +extension UnsafeMutablePointer { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal func moveInitialize( + @_nonEphemeral from source: UnsafeMutablePointer, count: Int + ) { + _debugPrecondition( + count >= 0, "UnsafeMutablePointer.moveInitialize with negative count") + if self < source || self >= source + count { + // initialize forward from a disjoint or following overlapping range. + Builtin.takeArrayFrontToBack( + Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue) + // This builtin is equivalent to: + // for i in 0..: _Pointer { // (self + i).initialize(to: source[i]) // } } +} +extension UnsafeMutablePointer where Pointee: ~Copyable { /// Update this pointer's initialized memory by moving the specified number /// of instances the source pointer's memory, leaving the source memory /// uninitialized. @@ -948,8 +1177,7 @@ public struct UnsafeMutablePointer: _Pointer { /// referenced by `source` and this pointer must not overlap. /// - count: The number of instances to move from `source` to this /// pointer's memory. `count` must not be negative. - @inlinable - @_silgen_name("$sSp10moveAssign4from5countySpyxG_SitF") + @_alwaysEmitIntoClient public func moveUpdate( @_nonEphemeral from source: UnsafeMutablePointer, count: Int ) { @@ -965,8 +1193,29 @@ public struct UnsafeMutablePointer: _Pointer { // self[i] = (source + i).move() // } } +} + +extension UnsafeMutablePointer { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + @_silgen_name("$sSp10moveAssign4from5countySpyxG_SitF") // To maintain ABI with moveAssign below + internal func moveUpdate( + @_nonEphemeral from source: UnsafeMutablePointer, count: Int + ) { + _debugPrecondition( + count >= 0, "UnsafeMutablePointer.moveUpdate(from:) with negative count") + _debugPrecondition( + self + count <= source || source + count <= self, + "moveUpdate overlapping range") + Builtin.assignTakeArray( + Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue) + // These builtins are equivalent to: + // for i in 0..: _Pointer { ) { moveUpdate(from: source, count: count) } +} +extension UnsafeMutablePointer where Pointee: ~Copyable { /// Deinitializes the specified number of values starting at this pointer. /// /// The region of memory starting at this pointer and covering `count` @@ -984,10 +1235,10 @@ public struct UnsafeMutablePointer: _Pointer { /// bound to the `Pointee` type. /// /// - Parameter count: The number of instances to deinitialize. `count` must - /// not be negative. + /// not be negative. /// - Returns: A raw pointer to the same address as this pointer. The memory /// referenced by the returned raw pointer is still bound to `Pointee`. - @inlinable + @_alwaysEmitIntoClient @discardableResult public func deinitialize(count: Int) -> UnsafeMutableRawPointer { _debugPrecondition(count >= 0, "UnsafeMutablePointer.deinitialize with negative count") @@ -996,7 +1247,23 @@ public struct UnsafeMutablePointer: _Pointer { Builtin.destroyArray(Pointee.self, _rawValue, count._builtinWordValue) return UnsafeMutableRawPointer(self) } +} + +extension UnsafeMutablePointer { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal func deinitialize(count: Int) -> UnsafeMutableRawPointer { + _debugPrecondition(count >= 0, "UnsafeMutablePointer.deinitialize with negative count") + // TODO: IRGen optimization when `count` value is statically known to be 1, + // then call `Builtin.destroy(Pointee.self, _rawValue)` instead. + Builtin.destroyArray(Pointee.self, _rawValue, count._builtinWordValue) + return UnsafeMutableRawPointer(self) + } +} +extension UnsafeMutablePointer /* where Pointee: ~Copyable */ { + // FIXME: We want this to have the constraint above, but that triggers a .swiftinterface issue. /// Executes the given closure while temporarily binding memory to /// the specified number of instances of the given type. /// @@ -1056,11 +1323,10 @@ public struct UnsafeMutablePointer: _Pointer { /// the return value for the `withMemoryRebound(to:capacity:_:)` method. /// - pointer: The pointer temporarily bound to `T`. /// - Returns: The return value, if any, of the `body` closure parameter. - @inlinable @_alwaysEmitIntoClient // This custom silgen name is chosen to not interfere with the old ABI @_silgen_name("_swift_se0333_UnsafeMutablePointer_withMemoryRebound") - public func withMemoryRebound( + public func withMemoryRebound( to type: T.Type, capacity count: Int, _ body: (_ pointer: UnsafeMutablePointer) throws -> Result @@ -1079,12 +1345,14 @@ public struct UnsafeMutablePointer: _Pointer { defer { Builtin.rebindMemory(_rawValue, binding) } return try body(.init(_rawValue)) } +} - // This unavailable implementation uses the expected mangled name +extension UnsafeMutablePointer { + // This obsolete implementation uses the expected mangled name // of `withMemoryRebound(to:capacity:_:)`, and provides // an entry point for any binary linked against the stdlib binary // for Swift 5.6 and older. - @available(*, unavailable) + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) @_silgen_name("$sSp17withMemoryRebound2to8capacity_qd_0_qd__m_Siqd_0_Spyqd__GKXEtKr0_lF") @usableFromInline internal func _legacy_se0333_withMemoryRebound( @@ -1096,7 +1364,9 @@ public struct UnsafeMutablePointer: _Pointer { defer { Builtin.rebindMemory(_rawValue, binding) } return try body(.init(_rawValue)) } +} +extension UnsafeMutablePointer where Pointee: ~Copyable { /// Reads or updates the pointee at the specified offset from this pointer. /// /// For a pointer `p`, the memory at `p + i` must be initialized when reading @@ -1110,7 +1380,7 @@ public struct UnsafeMutablePointer: _Pointer { /// /// - Parameter i: The offset from this pointer at which to access an /// instance, measured in strides of the pointer's `Pointee` type. - @inlinable + @_alwaysEmitIntoClient public subscript(i: Int) -> Pointee { @_transparent unsafeAddress { @@ -1121,7 +1391,25 @@ public struct UnsafeMutablePointer: _Pointer { return self + i } } +} + +extension UnsafeMutablePointer { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal subscript(i: Int) -> Pointee { + @_transparent + unsafeAddress { + return UnsafePointer(self + i) + } + @_transparent + nonmutating unsafeMutableAddress { + return self + i + } + } +} +extension UnsafeMutablePointer { /// Obtain a pointer to the stored property referred to by a key path. /// /// If the key path represents a computed property, diff --git a/stdlib/public/core/UnsafeRawPointer.swift b/stdlib/public/core/UnsafeRawPointer.swift index 057a5ceaa6d93..4fc9d389a6d9c 100644 --- a/stdlib/public/core/UnsafeRawPointer.swift +++ b/stdlib/public/core/UnsafeRawPointer.swift @@ -10,13 +10,12 @@ // //===----------------------------------------------------------------------===// -/// A raw pointer for accessing -/// untyped data. +/// A raw pointer for accessing untyped data. /// -/// The `UnsafeRawPointer` type provides no automated memory management, no type safety, -/// and no alignment guarantees. You are responsible for handling the life -/// cycle of any memory you work with through unsafe pointers, to avoid leaks -/// or undefined behavior. +/// The `UnsafeRawPointer` type provides no automated memory management, no type +/// safety, and no alignment guarantees. You are responsible for handling the +/// life cycle of any memory you work with through unsafe pointers, to avoid +/// leaks or undefined behavior. /// /// Memory that you manually manage can be either *untyped* or *bound* to a /// specific type. You use the `UnsafeRawPointer` type to access and @@ -26,14 +25,14 @@ /// Understanding a Pointer's Memory State /// ====================================== /// -/// The memory referenced by an `UnsafeRawPointer` instance can be in one of several -/// states. Many pointer operations must only be applied to pointers with -/// memory in a specific state---you must keep track of the state of the +/// The memory referenced by an `UnsafeRawPointer` instance can be in one of +/// several states. Many pointer operations must only be applied to pointers +/// with memory in a specific state---you must keep track of the state of the /// memory you are working with and understand the changes to that state that -/// different operations perform. Memory can be untyped and uninitialized, -/// bound to a type and uninitialized, or bound to a type and initialized to a -/// value. Finally, memory that was allocated previously may have been -/// deallocated, leaving existing pointers referencing unallocated memory. +/// different operations perform. Memory can be untyped and uninitialized, bound +/// to a type and uninitialized, or bound to a type and initialized to a value. +/// Finally, memory that was allocated previously may have been deallocated, +/// leaving existing pointers referencing unallocated memory. /// /// Raw, Uninitialized Memory /// ------------------------- @@ -99,8 +98,8 @@ /// Implicit Casting and Bridging /// ============================= /// -/// When calling a function or method with an `UnsafeRawPointer` parameter, you can pass -/// an instance of that specific pointer type, pass an instance of a +/// When calling a function or method with an `UnsafeRawPointer` parameter, you +/// can pass an instance of that specific pointer type, pass an instance of a /// compatible pointer type, or use Swift's implicit bridging to pass a /// compatible pointer. /// @@ -113,8 +112,8 @@ /// } /// /// As is typical in Swift, you can call the `print(address:as:)` function with -/// an `UnsafeRawPointer` instance. This example passes `rawPointer` as the initial -/// parameter. +/// an `UnsafeRawPointer` instance. This example passes `rawPointer` as the +/// initial parameter. /// /// // 'rawPointer' points to memory initialized with `Int` values. /// let rawPointer: UnsafeRawPointer = ... diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift index 6ce080a20092c..2e016ff3fd935 100644 --- a/stdlib/public/core/VarArgs.swift +++ b/stdlib/public/core/VarArgs.swift @@ -350,7 +350,7 @@ extension OpaquePointer: CVarArg { } } -extension UnsafePointer: CVarArg { +extension UnsafePointer: CVarArg where Pointee: ~Copyable { /// Transform `self` into a series of machine words that can be /// appropriately interpreted by C varargs. @inlinable // c-abi @@ -359,7 +359,7 @@ extension UnsafePointer: CVarArg { } } -extension UnsafeMutablePointer: CVarArg { +extension UnsafeMutablePointer: CVarArg where Pointee: ~Copyable { /// Transform `self` into a series of machine words that can be /// appropriately interpreted by C varargs. @inlinable // c-abi From 51925c5e11630382da589ac88e7b23441326937d Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Thu, 29 Feb 2024 12:05:04 -0800 Subject: [PATCH 03/19] [stdlib] Optional: Initial support for noncopyable payloads - Enable BorrowingSwitch feature within the stdlib - ExpressibleByNilLiteral: Add retroactive support for noncopyable conforming types - Optional: draft an API surface for noncopyable payloads [stdlib] Oops, the ExpressibleByNilLiteral conformance kept its implicit copyability --- stdlib/public/core/CMakeLists.txt | 1 + stdlib/public/core/CompilerProtocols.swift | 2 +- stdlib/public/core/NFC.swift | 2 +- stdlib/public/core/Optional.swift | 303 ++++++++++++++++++--- 4 files changed, 271 insertions(+), 37 deletions(-) diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index cf9da0995ca2d..ea28b0830aa88 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -314,6 +314,7 @@ list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "Macros") list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "FreestandingMacros") list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "Extern") list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "BitwiseCopyable") +list(APPEND swift_stdlib_compile_flags "-enable-experimental-feature" "BorrowingSwitch") if("${SWIFT_NATIVE_SWIFT_TOOLS_PATH}" STREQUAL "") set(swift_bin_dir "${CMAKE_BINARY_DIR}/bin") diff --git a/stdlib/public/core/CompilerProtocols.swift b/stdlib/public/core/CompilerProtocols.swift index a0709c94251d2..f24af69a95cc9 100644 --- a/stdlib/public/core/CompilerProtocols.swift +++ b/stdlib/public/core/CompilerProtocols.swift @@ -266,7 +266,7 @@ public protocol CaseIterable { /// `Optional` type conforms to `ExpressibleByNilLiteral`. /// `ExpressibleByNilLiteral` conformance for types that use `nil` for other /// purposes is discouraged. -public protocol ExpressibleByNilLiteral { +public protocol ExpressibleByNilLiteral: ~Copyable { /// Creates an instance initialized with `nil`. init(nilLiteral: ()) } diff --git a/stdlib/public/core/NFC.swift b/stdlib/public/core/NFC.swift index 7e68e83cebe83..35ea4ceaab2e2 100644 --- a/stdlib/public/core/NFC.swift +++ b/stdlib/public/core/NFC.swift @@ -206,7 +206,7 @@ extension Unicode._InternalNFC.Iterator: IteratorProtocol { } // If we have a leftover composee, make sure to return it. - return composee._take() + return composee.take() } } diff --git a/stdlib/public/core/Optional.swift b/stdlib/public/core/Optional.swift index 5ffec517b0d93..aee4dea89b565 100644 --- a/stdlib/public/core/Optional.swift +++ b/stdlib/public/core/Optional.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2024 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 @@ -118,7 +118,7 @@ /// Unconditionally unwrapping a `nil` instance with `!` triggers a runtime /// error. @frozen -public enum Optional: ExpressibleByNilLiteral { +public enum Optional: ~Copyable { // The compiler has special knowledge of Optional, including the fact // that it is an `enum` with cases named `none` and `some`. @@ -130,11 +130,41 @@ public enum Optional: ExpressibleByNilLiteral { /// The presence of a value, stored as `Wrapped`. case some(Wrapped) +} + +extension Optional: Copyable /* where Wrapped: Copyable */ {} + +extension Optional: ExpressibleByNilLiteral where Wrapped: ~Copyable { + /// Creates an instance initialized with `nil`. + /// + /// Do not call this initializer directly. It is used by the compiler when you + /// initialize an `Optional` instance with a `nil` literal. For example: + /// + /// var i: Index? = nil + /// + /// In this example, the assignment to the `i` variable calls this + /// initializer behind the scenes. + @_transparent + public init(nilLiteral: ()) { + self = .none + } +} +extension Optional where Wrapped: ~Copyable { /// Creates an instance that stores the given value. + @_alwaysEmitIntoClient @_transparent - public init(_ some: Wrapped) { self = .some(some) } + public init(_ some: consuming Wrapped) { self = .some(some) } +} + +extension Optional { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal init(_ some: Wrapped) { self = .some(some) } +} +extension Optional { /// Evaluates the given closure when this `Optional` instance is not `nil`, /// passing the unwrapped value as a parameter. /// @@ -167,7 +197,37 @@ public enum Optional: ExpressibleByNilLiteral { return .none } } +} + +extension Optional where Wrapped: ~Copyable { + @_alwaysEmitIntoClient + public consuming func consumingMap( + _ transform: (consuming Wrapped) throws -> U + ) rethrows -> U? { + switch /*consume*/ self { + case .some(let y): + return .some(try transform(consume y)) + case .none: + return .none + } + } + +#if $BorrowingSwitch + @_alwaysEmitIntoClient + public borrowing func borrowingMap( + _ transform: (borrowing Wrapped) throws -> U + ) rethrows -> U? { + switch self { + case .some(_borrowing y): + return .some(try transform(y)) + case .none: + return .none + } + } +#endif +} +extension Optional { /// Evaluates the given closure when this `Optional` instance is not `nil`, /// passing the unwrapped value as a parameter. /// @@ -184,7 +244,7 @@ public enum Optional: ExpressibleByNilLiteral { /// // Prints "Optional(1764)" /// /// - Parameter transform: A closure that takes the unwrapped value - /// of the instance. + /// of the instance. /// - Returns: The result of the given closure. If this instance is `nil`, /// returns `nil`. @inlinable @@ -198,21 +258,39 @@ public enum Optional: ExpressibleByNilLiteral { return .none } } +} - /// Creates an instance initialized with `nil`. - /// - /// Do not call this initializer directly. It is used by the compiler when you - /// initialize an `Optional` instance with a `nil` literal. For example: - /// - /// var i: Index? = nil - /// - /// In this example, the assignment to the `i` variable calls this - /// initializer behind the scenes. - @_transparent - public init(nilLiteral: ()) { - self = .none +extension Optional where Wrapped: ~Copyable { + @_alwaysEmitIntoClient + @inlinable + public consuming func consumingFlatMap( + _ transform: (consuming Wrapped) throws -> U? + ) rethrows -> U? { + switch consume self { + case .some(let y): + return try transform(consume y) + case .none: + return .none + } + } + +#if $BorrowingSwitch + @_alwaysEmitIntoClient + @inlinable + public func borrowingFlatMap( + _ transform: (borrowing Wrapped) throws -> U? + ) rethrows -> U? { + switch self { + case .some(_borrowing y): + return try transform(y) + case .none: + return .none + } } +#endif +} +extension Optional { /// The wrapped value of this instance, unwrapped without checking whether /// the instance is `nil`. /// @@ -246,13 +324,29 @@ public enum Optional: ExpressibleByNilLiteral { _debugPreconditionFailure("unsafelyUnwrapped of nil optional") } } +} + +extension Optional where Wrapped: ~Copyable { + // FIXME(NCG): Do we want this? It seems like we do. + @_alwaysEmitIntoClient + public consuming func consumingUnsafelyUnwrap() -> Wrapped { + switch consume self { + case .some(let x): + return x + case .none: + _debugPreconditionFailure("consumingUsafelyUnwrap of nil optional") + } + } +} +extension Optional { /// - Returns: `unsafelyUnwrapped`. /// /// This version is for internal stdlib use; it avoids any checking /// overhead for users, even in Debug builds. @inlinable internal var _unsafelyUnwrappedUnchecked: Wrapped { + // FIXME(NCG): Migrate to the function below and obsolete this. @inline(__always) get { if let x = self { @@ -261,7 +355,19 @@ public enum Optional: ExpressibleByNilLiteral { _internalInvariantFailure("_unsafelyUnwrappedUnchecked of nil optional") } } +} + +extension Optional where Wrapped: ~Copyable { + @_alwaysEmitIntoClient + internal consuming func _unsafelyUnwrappedUnchecked2() -> Wrapped { + if let x = self { + return x + } + _internalInvariantFailure("_unsafelyUnwrappedUnchecked of nil optional") + } +} +extension Optional where Wrapped: ~Copyable { /// Takes the wrapped value being stored in this instance and returns it while /// also setting the instance to `nil`. If there is no value being stored in /// this instance, this returns `nil` instead. @@ -278,14 +384,11 @@ public enum Optional: ExpressibleByNilLiteral { /// /// - Returns: The wrapped value being stored in this instance. If this /// instance is `nil`, returns `nil`. - internal mutating func _take() -> Wrapped? { - switch self { - case .some(let wrapped): - self = nil - return wrapped - case .none: - return nil - } + @_alwaysEmitIntoClient // FIXME(NCG): This is new in Swift 6 + public mutating func take() -> Self { + let result = consume self + self = nil + return result } } @@ -437,7 +540,8 @@ public struct _OptionalNilComparisonType: ExpressibleByNilLiteral { } } -extension Optional { +#if $BorrowingSwitch +extension Optional where Wrapped: ~Copyable { /// Returns a Boolean value indicating whether an argument matches `nil`. /// /// You can use the pattern-matching operator (`~=`) to test whether an @@ -469,7 +573,10 @@ extension Optional { /// - lhs: A `nil` literal. /// - rhs: A value to match against `nil`. @_transparent - public static func ~=(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool { + public static func ~=( + lhs: _OptionalNilComparisonType, + rhs: borrowing Wrapped? + ) -> Bool { switch rhs { case .some: return false @@ -503,7 +610,10 @@ extension Optional { /// - lhs: A value to compare to `nil`. /// - rhs: A `nil` literal. @_transparent - public static func ==(lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool { + public static func ==( + lhs: borrowing Wrapped?, + rhs: _OptionalNilComparisonType + ) -> Bool { switch lhs { case .some: return false @@ -534,7 +644,10 @@ extension Optional { /// - lhs: A value to compare to `nil`. /// - rhs: A `nil` literal. @_transparent - public static func !=(lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool { + public static func !=( + lhs: borrowing Wrapped?, + rhs: _OptionalNilComparisonType + ) -> Bool { switch lhs { case .some: return true @@ -565,7 +678,10 @@ extension Optional { /// - lhs: A `nil` literal. /// - rhs: A value to compare to `nil`. @_transparent - public static func ==(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool { + public static func ==( + lhs: _OptionalNilComparisonType, + rhs: borrowing Wrapped? + ) -> Bool { switch rhs { case .some: return false @@ -596,7 +712,10 @@ extension Optional { /// - lhs: A `nil` literal. /// - rhs: A value to compare to `nil`. @_transparent - public static func !=(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool { + public static func !=( + lhs: _OptionalNilComparisonType, + rhs: borrowing Wrapped? + ) -> Bool { switch rhs { case .some: return true @@ -606,6 +725,86 @@ extension Optional { } } +extension Optional { + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal static func ~=( + lhs: _OptionalNilComparisonType, + rhs: Wrapped? + ) -> Bool { + switch rhs { + case .some: + return false + case .none: + return true + } + } + + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal static func ==( + lhs: Wrapped?, + rhs: _OptionalNilComparisonType + ) -> Bool { + switch lhs { + case .some: + return false + case .none: + return true + } + } + + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal static func !=( + lhs: Wrapped?, + rhs: _OptionalNilComparisonType + ) -> Bool { + switch lhs { + case .some: + return true + case .none: + return false + } + } + + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal static func ==( + lhs: _OptionalNilComparisonType, + rhs: Wrapped? + ) -> Bool { + switch rhs { + case .some: + return false + case .none: + return true + } + } + + // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal static func !=( + lhs: _OptionalNilComparisonType, + rhs: Wrapped? + ) -> Bool { + switch rhs { + case .some: + return true + case .none: + return false + } + } +} +#else +#error("FIXME(NCG): Fill this out.") +#endif + /// Performs a nil-coalescing operation, returning the wrapped value of an /// `Optional` instance or a default value. /// @@ -639,8 +838,25 @@ extension Optional { /// - defaultValue: A value to use as a default. `defaultValue` is the same /// type as the `Wrapped` type of `optional`. @_transparent -public func ?? (optional: T?, defaultValue: @autoclosure () throws -> T) - rethrows -> T { +@_alwaysEmitIntoClient +public func ?? ( + optional: consuming T?, + defaultValue: @autoclosure () throws -> T +) rethrows -> T { + switch consume optional { + case .some(let value): + return value + case .none: + return try defaultValue() + } +} + +@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) +@usableFromInline +internal func ?? ( + optional: T?, + defaultValue: @autoclosure () throws -> T +) rethrows -> T { switch optional { case .some(let value): return value @@ -692,8 +908,25 @@ public func ?? (optional: T?, defaultValue: @autoclosure () throws -> T) /// - defaultValue: A value to use as a default. `defaultValue` and /// `optional` have the same type. @_transparent -public func ?? (optional: T?, defaultValue: @autoclosure () throws -> T?) - rethrows -> T? { +@_alwaysEmitIntoClient +public func ?? ( + optional: consuming T?, + defaultValue: @autoclosure () throws -> T? +) rethrows -> T? { + switch optional { + case .some(let value): + return value + case .none: + return try defaultValue() + } +} + +@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) +@usableFromInline +internal func ?? ( + optional: T?, + defaultValue: @autoclosure () throws -> T? +) rethrows -> T? { switch optional { case .some(let value): return value @@ -781,6 +1014,6 @@ extension Optional: _ObjectiveCBridgeable { } #endif -extension Optional: Sendable where Wrapped: Sendable { } +extension Optional: Sendable where Wrapped: ~Copyable & Sendable { } extension Optional: _BitwiseCopyable where Wrapped: _BitwiseCopyable { } From 8adc6aa59ff620c4fdd0f968ee75e18996e39066 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Mon, 4 Mar 2024 20:13:26 -0800 Subject: [PATCH 04/19] [stdlib] UnsafeRawPointer: new interactions with noncopyable types --- stdlib/public/core/UnsafeRawPointer.swift | 294 +++++++++++++++------- 1 file changed, 209 insertions(+), 85 deletions(-) diff --git a/stdlib/public/core/UnsafeRawPointer.swift b/stdlib/public/core/UnsafeRawPointer.swift index 4fc9d389a6d9c..3e24ce8405b26 100644 --- a/stdlib/public/core/UnsafeRawPointer.swift +++ b/stdlib/public/core/UnsafeRawPointer.swift @@ -181,7 +181,12 @@ public struct UnsafeRawPointer: _Pointer { public init(_ _rawValue: Builtin.RawPointer) { self._rawValue = _rawValue } +} + +@available(*, unavailable) +extension UnsafeRawPointer: Sendable {} +extension UnsafeRawPointer { /// Creates a new raw pointer from the given typed pointer. /// /// Use this initializer to explicitly convert `other` to an `UnsafeRawPointer` @@ -190,7 +195,8 @@ public struct UnsafeRawPointer: _Pointer { /// /// - Parameter other: The typed pointer to convert. @_transparent - public init(@_nonEphemeral _ other: UnsafePointer) { + // FIXME(NCG): @_preInverseGenerics + public init(@_nonEphemeral _ other: UnsafePointer) { _rawValue = other._rawValue } @@ -203,11 +209,14 @@ public struct UnsafeRawPointer: _Pointer { /// - Parameter other: The typed pointer to convert. If `other` is `nil`, the /// result is `nil`. @_transparent - public init?(@_nonEphemeral _ other: UnsafePointer?) { + // FIXME(NCG): @_preInverseGenerics + public init?(@_nonEphemeral _ other: UnsafePointer?) { guard let unwrapped = other else { return nil } _rawValue = unwrapped._rawValue } +} +extension UnsafeRawPointer { /// Creates a new raw pointer from the given mutable raw pointer. /// /// Use this initializer to explicitly convert `other` to an `UnsafeRawPointer` @@ -233,7 +242,9 @@ public struct UnsafeRawPointer: _Pointer { guard let unwrapped = other else { return nil } _rawValue = unwrapped._rawValue } +} +extension UnsafeRawPointer { /// Creates a new raw pointer from the given typed pointer. /// /// Use this initializer to explicitly convert `other` to an `UnsafeRawPointer` @@ -242,7 +253,8 @@ public struct UnsafeRawPointer: _Pointer { /// /// - Parameter other: The typed pointer to convert. @_transparent - public init(@_nonEphemeral _ other: UnsafeMutablePointer) { + // FIXME(NCG): @_preInverseGenerics + public init(@_nonEphemeral _ other: UnsafeMutablePointer) { _rawValue = other._rawValue } @@ -255,7 +267,8 @@ public struct UnsafeRawPointer: _Pointer { /// - Parameter other: The typed pointer to convert. If `other` is `nil`, the /// result is `nil`. @_transparent - public init?(@_nonEphemeral _ other: UnsafeMutablePointer?) { + // FIXME(NCG): @_preInverseGenerics + public init?(@_nonEphemeral _ other: UnsafeMutablePointer?) { guard let unwrapped = other else { return nil } _rawValue = unwrapped._rawValue } @@ -310,8 +323,9 @@ public struct UnsafeRawPointer: _Pointer { /// The number of bytes in this region is /// `count * MemoryLayout.stride`. @_transparent + // FIXME(NCG): @_preInverseGenerics @discardableResult - public func bindMemory( + public func bindMemory( to type: T.Type, capacity count: Int ) -> UnsafePointer { Builtin.bindMemory(_rawValue, count._builtinWordValue, type) @@ -369,9 +383,8 @@ public struct UnsafeRawPointer: _Pointer { /// the return value for the `withMemoryRebound(to:capacity:_:)` method. /// - pointer: The pointer temporarily bound to `T`. /// - Returns: The return value, if any, of the `body` closure parameter. - @inlinable @_alwaysEmitIntoClient - public func withMemoryRebound( + public func withMemoryRebound( to type: T.Type, capacity count: Int, _ body: (_ pointer: UnsafePointer) throws(E) -> Result @@ -397,7 +410,10 @@ public struct UnsafeRawPointer: _Pointer { /// - Parameter to: The type `T` that the memory has already been bound to. /// - Returns: A typed pointer to the same memory as this raw pointer. @_transparent - public func assumingMemoryBound(to: T.Type) -> UnsafePointer { + // FIXME(NCG): @_preInverseGenerics + public func assumingMemoryBound( + to: T.Type + ) -> UnsafePointer { return UnsafePointer(_rawValue) } @@ -416,7 +432,10 @@ public struct UnsafeRawPointer: _Pointer { /// `offset`. The returned instance is memory-managed and unassociated /// with the value in the memory referenced by this pointer. @inlinable - public func load(fromByteOffset offset: Int = 0, as type: T.Type) -> T { + public func load( + fromByteOffset offset: Int = 0, + as type: T.Type + ) -> T { _debugPrecondition(0 == (UInt(bitPattern: self + offset) & (UInt(MemoryLayout.alignment) - 1)), "load from misaligned raw pointer") @@ -433,6 +452,10 @@ public struct UnsafeRawPointer: _Pointer { #endif } + // FIXME(NCG): Add a consuming analogue of `load`, like `move(fromByteOffset:as:_:)` + // FIXME(NCG): Add a borrow analogue of `load`, like `withBorrow(fromByteOffset:as:_:)` + +#if $BitwiseCopyable /// Returns a new instance of the given type, constructed from the raw memory /// at the specified offset. /// @@ -455,16 +478,38 @@ public struct UnsafeRawPointer: _Pointer { /// - Returns: A new instance of type `T`, read from the raw bytes at /// `offset`. The returned instance isn't associated /// with the value in the range of memory referenced by this pointer. -#if $BitwiseCopyable @inlinable @_alwaysEmitIntoClient - public func loadUnaligned( + public func loadUnaligned( fromByteOffset offset: Int = 0, as type: T.Type ) -> T { return Builtin.loadRaw((self + offset)._rawValue) } #endif + + /// Returns a new instance of the given type, constructed from the raw memory + /// at the specified offset. + /// + /// This function only supports loading trivial types, + /// and will trap if this precondition is not met. + /// A trivial type does not contain any reference-counted property + /// within its in-memory representation. + /// The memory at this pointer plus `offset` must be laid out + /// identically to the in-memory representation of `T`. + /// + /// - Note: A trivial type can be copied with just a bit-for-bit copy without + /// any indirection or reference-counting operations. Generally, native + /// Swift types that do not contain strong or weak references or other + /// forms of indirection are trivial, as are imported C structs and enums. + /// + /// - Parameters: + /// - offset: The offset from this pointer, in bytes. `offset` must be + /// nonnegative. The default is zero. + /// - type: The type of the instance to create. + /// - Returns: A new instance of type `T`, read from the raw bytes at + /// `offset`. The returned instance isn't associated + /// with the value in the range of memory referenced by this pointer. @inlinable @_alwaysEmitIntoClient public func loadUnaligned( @@ -504,14 +549,15 @@ extension UnsafeRawPointer { /// - Returns: a pointer properly aligned to store a value of type `T`. @inlinable @_alwaysEmitIntoClient - public func alignedUp(for type: T.Type) -> Self { + public func alignedUp(for type: T.Type) -> Self { let mask = UInt(Builtin.alignof(T.self)) &- 1 let bits = (UInt(Builtin.ptrtoint_Word(_rawValue)) &+ mask) & ~mask _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") return .init(Builtin.inttoptr_Word(bits._builtinWordValue)) } - /// Obtain the preceding pointer properly aligned to store a value of type `T`. + /// Obtain the preceding pointer properly aligned to store a value of type + /// `T`. /// /// If `self` is properly aligned for accessing `T`, /// this function returns `self`. @@ -521,7 +567,7 @@ extension UnsafeRawPointer { /// - Returns: a pointer properly aligned to store a value of type `T`. @inlinable @_alwaysEmitIntoClient - public func alignedDown(for type: T.Type) -> Self { + public func alignedDown(for type: T.Type) -> Self { let mask = UInt(Builtin.alignof(T.self)) &- 1 let bits = UInt(Builtin.ptrtoint_Word(_rawValue)) & ~mask _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") @@ -550,7 +596,8 @@ extension UnsafeRawPointer { return .init(Builtin.inttoptr_Word(bits._builtinWordValue)) } - /// Obtain the preceding pointer whose bit pattern is a multiple of `alignment`. + /// Obtain the preceding pointer whose bit pattern is a multiple of + /// `alignment`. /// /// If the bit pattern of `self` is a multiple of `alignment`, /// this function returns `self`. @@ -576,10 +623,10 @@ extension UnsafeRawPointer { /// A raw pointer for accessing and manipulating /// untyped data. /// -/// The `UnsafeMutableRawPointer` type provides no automated memory management, no type safety, -/// and no alignment guarantees. You are responsible for handling the life -/// cycle of any memory you work with through unsafe pointers, to avoid leaks -/// or undefined behavior. +/// The `UnsafeMutableRawPointer` type provides no automated memory management, +/// no type safety, and no alignment guarantees. You are responsible for +/// handling the life cycle of any memory you work with through unsafe pointers, +/// to avoid leaks or undefined behavior. /// /// Memory that you manually manage can be either *untyped* or *bound* to a /// specific type. You use the `UnsafeMutableRawPointer` type to access and @@ -589,14 +636,14 @@ extension UnsafeRawPointer { /// Understanding a Pointer's Memory State /// ====================================== /// -/// The memory referenced by an `UnsafeMutableRawPointer` instance can be in one of several -/// states. Many pointer operations must only be applied to pointers with -/// memory in a specific state---you must keep track of the state of the +/// The memory referenced by an `UnsafeMutableRawPointer` instance can be in one +/// of several states. Many pointer operations must only be applied to pointers +/// with memory in a specific state---you must keep track of the state of the /// memory you are working with and understand the changes to that state that -/// different operations perform. Memory can be untyped and uninitialized, -/// bound to a type and uninitialized, or bound to a type and initialized to a -/// value. Finally, memory that was allocated previously may have been -/// deallocated, leaving existing pointers referencing unallocated memory. +/// different operations perform. Memory can be untyped and uninitialized, bound +/// to a type and uninitialized, or bound to a type and initialized to a value. +/// Finally, memory that was allocated previously may have been deallocated, +/// leaving existing pointers referencing unallocated memory. /// /// Raw, Uninitialized Memory /// ------------------------- @@ -667,10 +714,10 @@ extension UnsafeRawPointer { /// Implicit Casting and Bridging /// ============================= /// -/// When calling a function or method with an `UnsafeMutableRawPointer` parameter, you can pass -/// an instance of that specific pointer type, pass an instance of a -/// compatible pointer type, or use Swift's implicit bridging to pass a -/// compatible pointer. +/// When calling a function or method with an `UnsafeMutableRawPointer` +/// parameter, you can pass an instance of that specific pointer type, pass an +/// instance of a compatible pointer type, or use Swift's implicit bridging to +/// pass a compatible pointer. /// /// For example, the `print(address:as:)` function in the following code sample /// takes an `UnsafeMutableRawPointer` instance as its first parameter: @@ -681,8 +728,8 @@ extension UnsafeRawPointer { /// } /// /// As is typical in Swift, you can call the `print(address:as:)` function with -/// an `UnsafeMutableRawPointer` instance. This example passes `rawPointer` as the initial -/// parameter. +/// an `UnsafeMutableRawPointer` instance. This example passes `rawPointer` as +/// the initial parameter. /// /// // 'rawPointer' points to memory initialized with `Int` values. /// let rawPointer: UnsafeMutableRawPointer = ... @@ -727,9 +774,9 @@ extension UnsafeRawPointer { /// // Accessing 'numberPointer' is undefined behavior. @frozen public struct UnsafeMutableRawPointer: _Pointer { - + public typealias Pointee = UInt8 - + /// The underlying raw pointer. /// Implements conformance to the public protocol `_Pointer`. public let _rawValue: Builtin.RawPointer @@ -739,38 +786,45 @@ public struct UnsafeMutableRawPointer: _Pointer { public init(_ _rawValue: Builtin.RawPointer) { self._rawValue = _rawValue } +} + +@available(*, unavailable) +extension UnsafeMutableRawPointer: Sendable {} +extension UnsafeMutableRawPointer { /// Creates a new raw pointer from the given typed pointer. /// - /// Use this initializer to explicitly convert `other` to an `UnsafeMutableRawPointer` - /// instance. This initializer creates a new pointer to the same address as - /// `other` and performs no allocation or copying. + /// Use this initializer to explicitly convert `other` to an + /// `UnsafeMutableRawPointer` instance. This initializer creates a new pointer + /// to the same address as `other` and performs no allocation or copying. /// /// - Parameter other: The typed pointer to convert. @_transparent - public init(@_nonEphemeral _ other: UnsafeMutablePointer) { + // FIXME(NCG): @_preInverseGenerics + public init(@_nonEphemeral _ other: UnsafeMutablePointer) { _rawValue = other._rawValue } /// Creates a new raw pointer from the given typed pointer. /// - /// Use this initializer to explicitly convert `other` to an `UnsafeMutableRawPointer` - /// instance. This initializer creates a new pointer to the same address as - /// `other` and performs no allocation or copying. + /// Use this initializer to explicitly convert `other` to an + /// `UnsafeMutableRawPointer` instance. This initializer creates a new pointer + /// to the same address as `other` and performs no allocation or copying. /// /// - Parameter other: The typed pointer to convert. If `other` is `nil`, the /// result is `nil`. @_transparent - public init?(@_nonEphemeral _ other: UnsafeMutablePointer?) { + // FIXME(NCG): @_preInverseGenerics + public init?(@_nonEphemeral _ other: UnsafeMutablePointer?) { guard let unwrapped = other else { return nil } _rawValue = unwrapped._rawValue } /// Creates a new mutable raw pointer from the given immutable raw pointer. /// - /// Use this initializer to explicitly convert `other` to an `UnsafeMutableRawPointer` - /// instance. This initializer creates a new pointer to the same address as - /// `other` and performs no allocation or copying. + /// Use this initializer to explicitly convert `other` to an + /// `UnsafeMutableRawPointer` instance. This initializer creates a new pointer + /// to the same address as `other` and performs no allocation or copying. /// /// - Parameter other: The immutable raw pointer to convert. @_transparent @@ -780,9 +834,9 @@ public struct UnsafeMutableRawPointer: _Pointer { /// Creates a new mutable raw pointer from the given immutable raw pointer. /// - /// Use this initializer to explicitly convert `other` to an `UnsafeMutableRawPointer` - /// instance. This initializer creates a new pointer to the same address as - /// `other` and performs no allocation or copying. + /// Use this initializer to explicitly convert `other` to an + /// `UnsafeMutableRawPointer` instance. This initializer creates a new pointer + /// to the same address as `other` and performs no allocation or copying. /// /// - Parameter other: The immutable raw pointer to convert. If `other` is /// `nil`, the result is `nil`. @@ -803,7 +857,8 @@ public struct UnsafeMutableRawPointer: _Pointer { /// `UnsafeMutablePointer.allocate(capacity:)` static method instead. /// /// - Parameters: - /// - byteCount: The number of bytes to allocate. `byteCount` must not be negative. + /// - byteCount: The number of bytes to allocate. `byteCount` must not be + /// negative. /// - alignment: The alignment of the new region of allocated memory, in /// bytes. `alignment` must be a whole power of 2. /// - Returns: A pointer to a newly allocated region of memory. The memory is @@ -831,7 +886,8 @@ public struct UnsafeMutableRawPointer: _Pointer { byteCount._builtinWordValue, alignment._builtinWordValue)) } - /// Deallocates the previously allocated memory block referenced by this pointer. + /// Deallocates the previously allocated memory block referenced by this + /// pointer. /// /// The memory to be deallocated must be uninitialized or initialized to a /// trivial type. @@ -881,8 +937,9 @@ public struct UnsafeMutableRawPointer: _Pointer { /// The number of bytes in this region is /// `count * MemoryLayout.stride`. @_transparent + // FIXME(NCG): @_preInverseGenerics @discardableResult - public func bindMemory( + public func bindMemory( to type: T.Type, capacity count: Int ) -> UnsafeMutablePointer { Builtin.bindMemory(_rawValue, count._builtinWordValue, type) @@ -938,9 +995,8 @@ public struct UnsafeMutableRawPointer: _Pointer { /// the return value for the `withMemoryRebound(to:capacity:_:)` method. /// - pointer: The pointer temporarily bound to `T`. /// - Returns: The return value, if any, of the `body` closure parameter. - @inlinable @_alwaysEmitIntoClient - public func withMemoryRebound( + public func withMemoryRebound( to type: T.Type, capacity count: Int, _ body: (_ pointer: UnsafeMutablePointer) throws(E) -> Result @@ -966,7 +1022,10 @@ public struct UnsafeMutableRawPointer: _Pointer { /// - Parameter to: The type `T` that the memory has already been bound to. /// - Returns: A typed pointer to the same memory as this raw pointer. @_transparent - public func assumingMemoryBound(to: T.Type) -> UnsafeMutablePointer { + // FIXME(NCG): @_preInverseGenerics + public func assumingMemoryBound( + to: T.Type + ) -> UnsafeMutablePointer { return UnsafeMutablePointer(_rawValue) } @@ -1000,13 +1059,12 @@ public struct UnsafeMutableRawPointer: _Pointer { /// - value: The value used to initialize this memory. /// - Returns: A typed pointer to the memory referenced by this raw pointer. @discardableResult - @inlinable @_alwaysEmitIntoClient - public func initializeMemory( - as type: T.Type, to value: T + public func initializeMemory( + as type: T.Type, to value: consuming T ) -> UnsafeMutablePointer { Builtin.bindMemory(_rawValue, (1)._builtinWordValue, type) - Builtin.initialize(value, _rawValue) + Builtin.initialize(consume value, _rawValue) return UnsafeMutablePointer(_rawValue) } @@ -1019,8 +1077,8 @@ public struct UnsafeMutableRawPointer: _Pointer { /// accessing `T`. /// /// The following example allocates enough raw memory to hold four instances - /// of `Int8`, and then uses the `initializeMemory(as:repeating:count:)` method - /// to initialize the allocated memory. + /// of `Int8`, and then uses the `initializeMemory(as:repeating:count:)` + /// method to initialize the allocated memory. /// /// let count = 4 /// let bytesPointer = UnsafeMutableRawPointer.allocate( @@ -1033,15 +1091,16 @@ public struct UnsafeMutableRawPointer: _Pointer { /// int8Pointer.deallocate() /// /// After calling this method on a raw pointer `p`, the region starting at - /// `self` and continuing up to `p + count * MemoryLayout.stride` is bound - /// to type `T` and initialized. If `T` is a nontrivial type, you must - /// eventually deinitialize or move from the values in this region to avoid leaks. + /// `self` and continuing up to `p + count * MemoryLayout.stride` is bound + /// to type `T` and initialized. If `T` is a nontrivial type, you must + /// eventually deinitialize or move from the values in this region to avoid + /// leaks. /// /// - Parameters: /// - type: The type to bind this memory to. /// - repeatedValue: The instance to copy into memory. /// - count: The number of copies of `value` to copy into memory. `count` - /// must not be negative. + /// must not be negative. /// - Returns: A typed pointer to the memory referenced by this raw pointer. @inlinable @discardableResult @@ -1157,8 +1216,9 @@ public struct UnsafeMutableRawPointer: _Pointer { /// must not be negative. /// - Returns: A typed pointer to the memory referenced by this raw pointer. @inlinable + // FIXME(NCG): @_preInverseGenerics @discardableResult - public func moveInitializeMemory( + public func moveInitializeMemory( as type: T.Type, from source: UnsafeMutablePointer, count: Int ) -> UnsafeMutablePointer { _debugPrecondition( @@ -1206,7 +1266,10 @@ public struct UnsafeMutableRawPointer: _Pointer { /// `offset`. The returned instance is memory-managed and unassociated /// with the value in the memory referenced by this pointer. @inlinable - public func load(fromByteOffset offset: Int = 0, as type: T.Type) -> T { + public func load( + fromByteOffset offset: Int = 0, + as type: T.Type + ) -> T { _debugPrecondition(0 == (UInt(bitPattern: self + offset) & (UInt(MemoryLayout.alignment) - 1)), "load from misaligned raw pointer") @@ -1223,6 +1286,10 @@ public struct UnsafeMutableRawPointer: _Pointer { #endif } + // FIXME(NCG): Add a consuming analogue of `load`, like `move(fromByteOffset:as:_:)` + // FIXME(NCG): Add a borrow analogue of `load`, like `withBorrow(fromByteOffset:as:_:)` + +#if $BitwiseCopyable /// Returns a new instance of the given type, constructed from the raw memory /// at the specified offset. /// @@ -1245,16 +1312,38 @@ public struct UnsafeMutableRawPointer: _Pointer { /// - Returns: A new instance of type `T`, read from the raw bytes at /// `offset`. The returned instance isn't associated /// with the value in the range of memory referenced by this pointer. -#if $BitwiseCopyable @inlinable @_alwaysEmitIntoClient - public func loadUnaligned( + public func loadUnaligned( fromByteOffset offset: Int = 0, as type: T.Type ) -> T { return Builtin.loadRaw((self + offset)._rawValue) } #endif + + /// Returns a new instance of the given type, constructed from the raw memory + /// at the specified offset. + /// + /// This function only supports loading trivial types, + /// and will trap if this precondition is not met. + /// A trivial type does not contain any reference-counted property + /// within its in-memory representation. + /// The memory at this pointer plus `offset` must be laid out + /// identically to the in-memory representation of `T`. + /// + /// - Note: A trivial type can be copied with just a bit-for-bit copy without + /// any indirection or reference-counting operations. Generally, native + /// Swift types that do not contain strong or weak references or other + /// forms of indirection are trivial, as are imported C structs and enums. + /// + /// - Parameters: + /// - offset: The offset from this pointer, in bytes. `offset` must be + /// nonnegative. The default is zero. + /// - type: The type of the instance to create. + /// - Returns: A new instance of type `T`, read from the raw bytes at + /// `offset`. The returned instance isn't associated + /// with the value in the range of memory referenced by this pointer. @inlinable @_alwaysEmitIntoClient public func loadUnaligned( @@ -1274,6 +1363,7 @@ public struct UnsafeMutableRawPointer: _Pointer { } } +#if $BitwiseCopyable /// Stores the given value's bytes into raw memory at the specified offset. /// /// The type `T` to be stored must be a trivial type. The memory @@ -1309,10 +1399,9 @@ public struct UnsafeMutableRawPointer: _Pointer { /// - offset: The offset from this pointer, in bytes. `offset` must be /// nonnegative. The default is zero. /// - type: The type of `value`. -#if $BitwiseCopyable @inlinable @_alwaysEmitIntoClient - public func storeBytes( + public func storeBytes( of value: T, toByteOffset offset: Int = 0, as type: T.Type ) { #if $BuiltinStoreRaw @@ -1322,6 +1411,42 @@ public struct UnsafeMutableRawPointer: _Pointer { #endif } #endif + + /// Stores the given value's bytes into raw memory at the specified offset. + /// + /// The type `T` to be stored must be a trivial type. The memory + /// must also be uninitialized, initialized to `T`, or initialized to + /// another trivial type that is layout compatible with `T`. + /// + /// After calling `storeBytes(of:toByteOffset:as:)`, the memory is + /// initialized to the raw bytes of `value`. If the memory is bound to a + /// type `U` that is layout compatible with `T`, then it contains a value of + /// type `U`. Calling `storeBytes(of:toByteOffset:as:)` does not change the + /// bound type of the memory. + /// + /// - Note: A trivial type can be copied with just a bit-for-bit copy without + /// any indirection or reference-counting operations. Generally, native + /// Swift types that do not contain strong or weak references or other + /// forms of indirection are trivial, as are imported C structs and enums. + /// + /// If you need to store into memory a copy of a value of a type that isn't + /// trivial, you cannot use the `storeBytes(of:toByteOffset:as:)` method. + /// Instead, you must know either initialize the memory or, + /// if you know the memory was already bound to `type`, assign to the memory. + /// For example, to replace a value stored in a raw pointer `p`, + /// where `U` is the current type and `T` is the new type, use a typed + /// pointer to access and deinitialize the current value before initializing + /// the memory with a new value: + /// + /// let typedPointer = p.bindMemory(to: U.self, capacity: 1) + /// typedPointer.deinitialize(count: 1) + /// p.initializeMemory(as: T.self, repeating: newValue, count: 1) + /// + /// - Parameters: + /// - value: The value to store as raw bytes. + /// - offset: The offset from this pointer, in bytes. `offset` must be + /// nonnegative. The default is zero. + /// - type: The type of `value`. @inlinable @_alwaysEmitIntoClient // This custom silgen name is chosen to not interfere with the old ABI @@ -1354,10 +1479,10 @@ public struct UnsafeMutableRawPointer: _Pointer { #endif } - // This unavailable implementation uses the expected mangled name + // This obsolete implementation uses the expected mangled name // of `storeBytes(of:toByteOffset:as:)`, and provides an entry point for // any binary compiled against the stdlib binary for Swift 5.6 and older. - @available(*, unavailable) + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) @_silgen_name("$sSv10storeBytes2of12toByteOffset2asyx_SixmtlF") @usableFromInline func _legacy_se0349_storeBytes( of value: T, toByteOffset offset: Int = 0, as type: T.Type @@ -1389,7 +1514,7 @@ public struct UnsafeMutableRawPointer: _Pointer { /// Copies the specified number of bytes from the given raw pointer's memory /// into this pointer's memory. /// - /// If the `byteCount` bytes of memory referenced by this pointer are bound to + /// If the `byteCount` bytes of memory referenced by this pointer are bound to /// a type `T`, then `T` must be a trivial type, this pointer and `source` /// must be properly aligned for accessing `T`, and `byteCount` must be a /// multiple of `MemoryLayout.stride`. @@ -1397,7 +1522,7 @@ public struct UnsafeMutableRawPointer: _Pointer { /// The memory in the region `source..<(source + byteCount)` may overlap with /// the memory referenced by this pointer. /// - /// After calling `copyMemory(from:byteCount:)`, the `byteCount` bytes of + /// After calling `copyMemory(from:byteCount:)`, the `byteCount` bytes of /// memory referenced by this pointer are initialized to raw bytes. If the /// memory is bound to type `T`, then it contains values of type `T`. /// @@ -1405,7 +1530,8 @@ public struct UnsafeMutableRawPointer: _Pointer { /// - source: A pointer to the memory to copy bytes from. The memory in the /// region `source..<(source + byteCount)` must be initialized to a /// trivial type. - /// - byteCount: The number of bytes to copy. `byteCount` must not be negative. + /// - byteCount: The number of bytes to copy. `byteCount` must not be + /// negative. @inlinable public func copyMemory(from source: UnsafeRawPointer, byteCount: Int) { _debugPrecondition( @@ -1419,7 +1545,8 @@ extension UnsafeMutableRawPointer: Strideable { // custom version for raw pointers @_transparent public func advanced(by n: Int) -> UnsafeMutableRawPointer { - return UnsafeMutableRawPointer(Builtin.gepRaw_Word(_rawValue, n._builtinWordValue)) + return UnsafeMutableRawPointer( + Builtin.gepRaw_Word(_rawValue, n._builtinWordValue)) } } @@ -1434,14 +1561,15 @@ extension UnsafeMutableRawPointer { /// - Returns: a pointer properly aligned to store a value of type `T`. @inlinable @_alwaysEmitIntoClient - public func alignedUp(for type: T.Type) -> Self { + public func alignedUp(for type: T.Type) -> Self { let mask = UInt(Builtin.alignof(T.self)) &- 1 let bits = (UInt(Builtin.ptrtoint_Word(_rawValue)) &+ mask) & ~mask _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") return .init(Builtin.inttoptr_Word(bits._builtinWordValue)) } - /// Obtain the preceding pointer properly aligned to store a value of type `T`. + /// Obtain the preceding pointer properly aligned to store a value of type + /// `T`. /// /// If `self` is properly aligned for accessing `T`, /// this function returns `self`. @@ -1451,7 +1579,7 @@ extension UnsafeMutableRawPointer { /// - Returns: a pointer properly aligned to store a value of type `T`. @inlinable @_alwaysEmitIntoClient - public func alignedDown(for type: T.Type) -> Self { + public func alignedDown(for type: T.Type) -> Self { let mask = UInt(Builtin.alignof(T.self)) &- 1 let bits = UInt(Builtin.ptrtoint_Word(_rawValue)) & ~mask _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") @@ -1480,7 +1608,8 @@ extension UnsafeMutableRawPointer { return .init(Builtin.inttoptr_Word(bits._builtinWordValue)) } - /// Obtain the preceding pointer whose bit pattern is a multiple of `alignment`. + /// Obtain the preceding pointer whose bit pattern is a multiple of + /// `alignment`. /// /// If the bit pattern of `self` is a multiple of `alignment`, /// this function returns `self`. @@ -1526,8 +1655,3 @@ extension OpaquePointer { self._rawValue = unwrapped._rawValue } } - -@available(*, unavailable) -extension UnsafeRawPointer: Sendable { } -@available(*, unavailable) -extension UnsafeMutableRawPointer: Sendable { } From 904d20bcacbb7ea8443d711b86c8d11b9b306bf0 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Mon, 4 Mar 2024 21:17:17 -0800 Subject: [PATCH 05/19] [stdlib] OpaquePointer: new interactions with noncopyable types --- stdlib/public/core/CTypes.swift | 34 +++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/stdlib/public/core/CTypes.swift b/stdlib/public/core/CTypes.swift index 9386b8324f850..0b2206d405f0f 100644 --- a/stdlib/public/core/CTypes.swift +++ b/stdlib/public/core/CTypes.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2024 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 @@ -150,24 +150,40 @@ public struct OpaquePointer { internal init(_ v: Builtin.RawPointer) { self._rawValue = v } +} + +@available(*, unavailable) +extension OpaquePointer: Sendable {} - /// Creates an `OpaquePointer` from a given address in memory. +extension OpaquePointer { + /// Creates a new `OpaquePointer` from the given address, specified as a bit + /// pattern. + /// + /// - Parameter bitPattern: A bit pattern to use for the address of the new + /// pointer. If `bitPattern` is zero, the result is `nil`. @_transparent public init?(bitPattern: Int) { if bitPattern == 0 { return nil } self._rawValue = Builtin.inttoptr_Word(bitPattern._builtinWordValue) } - /// Creates an `OpaquePointer` from a given address in memory. + /// Creates a new `OpaquePointer` from the given address, specified as a bit + /// pattern. + /// + /// - Parameter bitPattern: A bit pattern to use for the address of the new + /// pointer. If `bitPattern` is zero, the result is `nil`. @_transparent public init?(bitPattern: UInt) { if bitPattern == 0 { return nil } self._rawValue = Builtin.inttoptr_Word(bitPattern._builtinWordValue) } +} +extension OpaquePointer { /// Converts a typed `UnsafePointer` to an opaque C pointer. @_transparent - public init(@_nonEphemeral _ from: UnsafePointer) { + // FIXME(NCG): @_preInverseGenerics + public init(@_nonEphemeral _ from: UnsafePointer) { self._rawValue = from._rawValue } @@ -175,13 +191,17 @@ public struct OpaquePointer { /// /// The result is `nil` if `from` is `nil`. @_transparent - public init?(@_nonEphemeral _ from: UnsafePointer?) { + // FIXME(NCG): @_preInverseGenerics + public init?(@_nonEphemeral _ from: UnsafePointer?) { guard let unwrapped = from else { return nil } self.init(unwrapped) } +} +extension OpaquePointer { /// Converts a typed `UnsafeMutablePointer` to an opaque C pointer. @_transparent + // FIXME(NCG): @_preInverseGenerics public init(@_nonEphemeral _ from: UnsafeMutablePointer) { self._rawValue = from._rawValue } @@ -190,6 +210,7 @@ public struct OpaquePointer { /// /// The result is `nil` if `from` is `nil`. @_transparent + // FIXME(NCG): @_preInverseGenerics public init?(@_nonEphemeral _ from: UnsafeMutablePointer?) { guard let unwrapped = from else { return nil } self.init(unwrapped) @@ -215,9 +236,6 @@ extension OpaquePointer: Hashable { } } -@available(*, unavailable) -extension OpaquePointer : Sendable { } - @_unavailableInEmbedded extension OpaquePointer: CustomDebugStringConvertible { /// A textual representation of the pointer, suitable for debugging. From 17808ba148d4250eca89b5eb1cba1f1a34eaf956 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Tue, 20 Feb 2024 15:24:19 -0800 Subject: [PATCH 06/19] [build] Enable noncopyable generics; disable anything that prevents toolchain builds from succeeding --- benchmark/CMakeLists.txt | 9 +++++++-- benchmark/utils/main.swift | 3 +++ utils/build-presets.ini | 14 ++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index ac4e903b562c0..9d5b4a13314e9 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -25,7 +25,10 @@ include(AddSwiftBenchmarkSuite) # Declarative Description of Benchmarks #===-----------------------------------------------------------------------===# -set(SWIFT_BENCH_MODULES +set(SWIFT_BENCH_MODULES) + +# FIXME(NCG): Temporarily disabled +set(SWIFT_BENCH_MODULES_DISABLED single-source/Ackermann single-source/AngryPhonebook single-source/AnyHashableWithAClass @@ -213,7 +216,9 @@ set(SWIFT_BENCH_MODULES cxx-source/ReadAccessor ) -set(SWIFT_MULTISOURCE_SWIFT_BENCHES +set(SWIFT_MULTISOURCE_SWIFT_BENCHES) +# FIXME(NCG): Temporarily disabled +set(SWIFT_MULTISOURCE_SWIFT_BENCHES_DISABLED) multi-source/PrimsSplit ) diff --git a/benchmark/utils/main.swift b/benchmark/utils/main.swift index dbc38c3f7654a..3aee08c1f45c2 100644 --- a/benchmark/utils/main.swift +++ b/benchmark/utils/main.swift @@ -14,6 +14,8 @@ import TestsUtils import DriverUtils + +#if false // FIXME(NCG): Temporarily disabled to enable dev toolchain generation import Ackermann import AngryPhonebook import AnyHashableWithAClass @@ -406,5 +408,6 @@ register(UTF16Decode.benchmarks) register(Walsh.benchmarks) register(WordCount.benchmarks) register(XorLoop.benchmarks) +#endif main() diff --git a/utils/build-presets.ini b/utils/build-presets.ini index a8ff85ce05560..0484a80bc41bc 100644 --- a/utils/build-presets.ini +++ b/utils/build-presets.ini @@ -1303,6 +1303,10 @@ build-swift-stdlib-unittest-extra # Don't build the benchmarks skip-build-benchmarks +# FIXME(NCG): Temporary additions for dev toolchain generation +enable-experimental-noncopyable-generics=1 +bootstrapping=hosttools + # When building for an Xcode toolchain, don't copy the Swift Resource/ directory # into the LLDB.framework. LLDB.framework will be installed alongside a Swift # compiler, so LLDB should use its resource directory directly. @@ -1339,10 +1343,12 @@ install-prefix=%(install_toolchain_dir)s/usr # Executes the lit tests for the installable package that is created # Assumes the swift-integration-tests repo is checked out -test-installable-package +# FIXME(NCG): Temporarily removed for dev toolchain generation +#test-installable-package # Make sure that we can build the benchmarks with swiftpm against the toolchain -toolchain-benchmarks +# FIXME(NCG): Temporarily removed for dev toolchain generation +#toolchain-benchmarks # If someone uses this for incremental builds, force reconfiguration. reconfigure @@ -1386,7 +1392,7 @@ darwin-toolchain-require-use-os-runtime=1 [preset: buildbot_osx_package] mixin-preset= mixin_osx_package_base - mixin_osx_package_test + #mixin_osx_package_test FIXME(NCG): Temporarily removed to allow dev toolchain generation mixin_lightweight_assertions,no-stdlib-asserts # SKIP LLDB TESTS (67923799) @@ -1405,7 +1411,7 @@ mixin-preset= [preset: buildbot_osx_package,no_assertions] mixin-preset= mixin_osx_package_base - mixin_osx_package_test + #mixin_osx_package_test FIXME(NCG): Temporarily removed to allow dev toolchain generation no-assertions From 21286860dbf37f82fd550c09248a6621a34b4f4e Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 6 Mar 2024 12:08:15 -0800 Subject: [PATCH 07/19] [stdlib] MemoryLayout: Adopt @_preInverseGenerics --- stdlib/public/core/MemoryLayout.swift | 64 ++++----------------------- 1 file changed, 9 insertions(+), 55 deletions(-) diff --git a/stdlib/public/core/MemoryLayout.swift b/stdlib/public/core/MemoryLayout.swift index dee1f30fa9a12..ca4f2fc5b725a 100644 --- a/stdlib/public/core/MemoryLayout.swift +++ b/stdlib/public/core/MemoryLayout.swift @@ -42,6 +42,9 @@ @frozen // namespace public enum MemoryLayout {} +@available(*, unavailable) +extension MemoryLayout : _BitwiseCopyable {} + extension MemoryLayout where T: ~Copyable { /// The contiguous memory footprint of `T`, in bytes. /// @@ -52,7 +55,7 @@ extension MemoryLayout where T: ~Copyable { /// When allocating memory for multiple instances of `T` using an unsafe /// pointer, use a multiple of the type's stride instead of its size. @_transparent - @_alwaysEmitIntoClient + @_preInverseGenerics public static var size: Int { return Int(Builtin.sizeof(T.self)) } @@ -65,7 +68,7 @@ extension MemoryLayout where T: ~Copyable { /// trades runtime performance for space efficiency. This value is always /// positive. @_transparent - @_alwaysEmitIntoClient + @_preInverseGenerics public static var stride: Int { return Int(Builtin.strideof(T.self)) } @@ -75,38 +78,12 @@ extension MemoryLayout where T: ~Copyable { /// Use the `alignment` property for a type when allocating memory using an /// unsafe pointer. This value is always positive. @_transparent - @_alwaysEmitIntoClient + @_preInverseGenerics public static var alignment: Int { return Int(Builtin.alignof(T.self)) } } -@available(*, unavailable) -extension MemoryLayout : _BitwiseCopyable {} - -extension MemoryLayout { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal static var size: Int { - return Int(Builtin.sizeof(T.self)) - } - - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal static var stride: Int { - return Int(Builtin.strideof(T.self)) - } - - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal static var alignment: Int { - return Int(Builtin.alignof(T.self)) - } -} - extension MemoryLayout where T: ~Copyable { /// Returns the contiguous memory footprint of the given instance. /// @@ -131,7 +108,7 @@ extension MemoryLayout where T: ~Copyable { /// - Parameter value: A value representative of the type to describe. /// - Returns: The size, in bytes, of the given value's type. @_transparent - @_alwaysEmitIntoClient + @_preInverseGenerics public static func size(ofValue value: borrowing T) -> Int { return MemoryLayout.size } @@ -160,7 +137,7 @@ extension MemoryLayout where T: ~Copyable { /// - Parameter value: A value representative of the type to describe. /// - Returns: The stride, in bytes, of the given value's type. @_transparent - @_alwaysEmitIntoClient + @_preInverseGenerics public static func stride(ofValue value: borrowing T) -> Int { return MemoryLayout.stride } @@ -186,35 +163,12 @@ extension MemoryLayout where T: ~Copyable { /// - Returns: The default memory alignment, in bytes, of the given value's /// type. This value is always positive. @_transparent - @_alwaysEmitIntoClient + @_preInverseGenerics public static func alignment(ofValue value: borrowing T) -> Int { return MemoryLayout.alignment } } -extension MemoryLayout { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal static func size(ofValue value: borrowing T) -> Int { - return MemoryLayout.size - } - - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal static func stride(ofValue value: borrowing T) -> Int { - return MemoryLayout.stride - } - - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal static func alignment(ofValue value: borrowing T) -> Int { - return MemoryLayout.alignment - } -} - extension MemoryLayout { /// Returns the offset of an inline stored property within a type's in-memory /// representation. From 27471da120289f4f509a87568dd613aaabce3f37 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 6 Mar 2024 12:27:36 -0800 Subject: [PATCH 08/19] [stdlib] UnsafePointer: Adopt @_preInverseGenerics --- stdlib/public/core/MigrationSupport.swift | 10 +- stdlib/public/core/Pointer.swift | 10 +- stdlib/public/core/UnsafePointer.swift | 323 ++++------------------ stdlib/public/core/VarArgs.swift | 2 + 4 files changed, 63 insertions(+), 282 deletions(-) diff --git a/stdlib/public/core/MigrationSupport.swift b/stdlib/public/core/MigrationSupport.swift index c04ff068c989c..cbdb1532b1c1f 100644 --- a/stdlib/public/core/MigrationSupport.swift +++ b/stdlib/public/core/MigrationSupport.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2024 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 @@ -425,9 +425,7 @@ extension UnsafeMutableRawPointer: _CustomPlaygroundQuickLookable { } } -extension UnsafePointer: _CustomPlaygroundQuickLookable -where Pointee: ~Copyable // FIXME: Remove this (rdar://123262870) -{ +extension UnsafePointer: _CustomPlaygroundQuickLookable { private var summary: String { let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue)))) return ptrValue == 0 @@ -441,9 +439,7 @@ where Pointee: ~Copyable // FIXME: Remove this (rdar://123262870) } } -extension UnsafeMutablePointer: _CustomPlaygroundQuickLookable -where Pointee: ~Copyable // FIXME: Remove this (rdar://123262870) -{ +extension UnsafeMutablePointer: _CustomPlaygroundQuickLookable { private var summary: String { let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue)))) return ptrValue == 0 diff --git a/stdlib/public/core/Pointer.swift b/stdlib/public/core/Pointer.swift index 3e4640ea56f20..e2bb1817088e7 100644 --- a/stdlib/public/core/Pointer.swift +++ b/stdlib/public/core/Pointer.swift @@ -25,9 +25,13 @@ public typealias _CustomDebugStringConvertibleOrNone = Any /// A stdlib-internal protocol modeled by the intrinsic pointer types, /// UnsafeMutablePointer, UnsafePointer, UnsafeRawPointer, /// UnsafeMutableRawPointer, and AutoreleasingUnsafeMutablePointer. -public protocol _Pointer -: Hashable, Strideable, _CustomDebugStringConvertibleOrNone, _CustomReflectableOrNone -, _BitwiseCopyable { +public protocol _Pointer: + Hashable, + Strideable, + _CustomDebugStringConvertibleOrNone, + _CustomReflectableOrNone, + _BitwiseCopyable +{ /// A type that represents the distance between two pointers. typealias Distance = Int diff --git a/stdlib/public/core/UnsafePointer.swift b/stdlib/public/core/UnsafePointer.swift index d58ffe5823fd9..a1331b9c13166 100644 --- a/stdlib/public/core/UnsafePointer.swift +++ b/stdlib/public/core/UnsafePointer.swift @@ -213,21 +213,15 @@ public struct UnsafePointer: _Pointer, Copyable { public let _rawValue: Builtin.RawPointer /// Creates an `UnsafePointer` from a builtin raw pointer. - @_alwaysEmitIntoClient @_transparent + @_preInverseGenerics public init(_ _rawValue: Builtin.RawPointer) { self._rawValue = _rawValue } } -extension UnsafePointer { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal init(_ _rawValue: Builtin.RawPointer) { - self._rawValue = _rawValue - } -} +@available(*, unavailable) +extension UnsafePointer: Sendable where Pointee: ~Copyable {} extension UnsafePointer where Pointee: ~Copyable { /// Deallocates the memory block previously allocated at this pointer. @@ -235,7 +229,8 @@ extension UnsafePointer where Pointee: ~Copyable { /// This pointer must be a pointer to the start of a previously allocated /// memory block. The memory must not be initialized or `Pointee` must be a /// trivial type. - @_alwaysEmitIntoClient + @inlinable + @_preInverseGenerics public func deallocate() { // Passing zero alignment to the runtime forces "aligned // deallocation". Since allocation via `UnsafeMutable[Raw][Buffer]Pointer` @@ -245,25 +240,13 @@ extension UnsafePointer where Pointee: ~Copyable { } } -extension UnsafePointer { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal func deallocate() { - // Passing zero alignment to the runtime forces "aligned - // deallocation". Since allocation via `UnsafeMutable[Raw][Buffer]Pointer` - // always uses the "aligned allocation" path, this ensures that the - // runtime's allocation and deallocation paths are compatible. - Builtin.deallocRaw(_rawValue, (-1)._builtinWordValue, (0)._builtinWordValue) - } -} - extension UnsafePointer where Pointee: ~Copyable { /// Accesses the instance referenced by this pointer. /// /// When reading from the `pointee` property, the instance referenced by /// this pointer must already be initialized. - @_alwaysEmitIntoClient + @inlinable + @_preInverseGenerics public var pointee: Pointee { @_transparent unsafeAddress { return self @@ -271,17 +254,6 @@ extension UnsafePointer where Pointee: ~Copyable { } } -extension UnsafePointer { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal var pointee: Pointee { - unsafeAddress { - return self - } - } -} - extension UnsafePointer where Pointee: ~Copyable { /// Accesses the pointee at the specified offset from this pointer. /// @@ -290,7 +262,8 @@ extension UnsafePointer where Pointee: ~Copyable { /// /// - Parameter i: The offset from this pointer at which to access an /// instance, measured in strides of the pointer's `Pointee` type. - @_alwaysEmitIntoClient + @inlinable + @_preInverseGenerics public subscript(i: Int) -> Pointee { @_transparent unsafeAddress { @@ -299,18 +272,6 @@ extension UnsafePointer where Pointee: ~Copyable { } } -extension UnsafePointer { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal subscript(i: Int) -> Pointee { - @_transparent - unsafeAddress { - return self + i - } - } -} - extension UnsafePointer where Pointee: ~Copyable { /// Executes the given closure while temporarily binding memory to /// the specified number of instances of type `T`. @@ -374,9 +335,6 @@ extension UnsafePointer where Pointee: ~Copyable { /// - pointer: The pointer temporarily bound to `T`. /// - Returns: The return value, if any, of the `body` closure parameter. @_alwaysEmitIntoClient - // This custom silgen name is chosen to not interfere with the old ABI - @_silgen_name("_swift_se0333_UnsafePointer_withMemoryRebound") - // TODO: Remove @_silgen_name once ~Copyable can be a thing above public func withMemoryRebound( to type: T.Type, capacity count: Int, @@ -441,8 +399,9 @@ extension UnsafePointer { } } -extension UnsafePointer { +extension UnsafePointer where Pointee: ~Copyable { @inlinable // unsafe-performance + @_preInverseGenerics internal static var _max: UnsafePointer { return UnsafePointer( bitPattern: 0 as Int &- MemoryLayout.stride @@ -646,18 +605,23 @@ public struct UnsafeMutablePointer: _Pointer, Copyable { public let _rawValue: Builtin.RawPointer /// Creates an `UnsafeMutablePointer` from a builtin raw pointer. - @_alwaysEmitIntoClient @_transparent + @_preInverseGenerics public init(_ _rawValue: Builtin.RawPointer) { self._rawValue = _rawValue } +} + +@available(*, unavailable) +extension UnsafeMutablePointer: Sendable where Pointee: ~Copyable {} +extension UnsafeMutablePointer where Pointee: ~Copyable { /// Creates a mutable typed pointer referencing the same memory as the given /// immutable pointer. /// /// - Parameter other: The immutable pointer to convert. - @_alwaysEmitIntoClient @_transparent + @_preInverseGenerics public init(@_nonEphemeral mutating other: UnsafePointer) { self._rawValue = other._rawValue } @@ -667,19 +631,19 @@ public struct UnsafeMutablePointer: _Pointer, Copyable { /// /// - Parameter other: The immutable pointer to convert. If `other` is `nil`, /// the result is `nil`. - @_alwaysEmitIntoClient @_transparent + @_preInverseGenerics public init?(@_nonEphemeral mutating other: UnsafePointer?) { guard let unwrapped = other else { return nil } self.init(mutating: unwrapped) } - + /// Creates a mutable typed pointer referencing the same memory as the /// given mutable pointer. /// /// - Parameter other: The pointer to convert. - @_alwaysEmitIntoClient @_transparent + @_preInverseGenerics public init(@_nonEphemeral _ other: UnsafeMutablePointer) { self._rawValue = other._rawValue } @@ -689,53 +653,14 @@ public struct UnsafeMutablePointer: _Pointer, Copyable { /// /// - Parameter other: The pointer to convert. If `other` is `nil`, the /// result is `nil`. - @_alwaysEmitIntoClient @_transparent + @_preInverseGenerics public init?(@_nonEphemeral _ other: UnsafeMutablePointer?) { guard let unwrapped = other else { return nil } self.init(unwrapped) } } -extension UnsafeMutablePointer { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal init(_ _rawValue: Builtin.RawPointer) { - self._rawValue = _rawValue - } - - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal init(@_nonEphemeral mutating other: UnsafePointer) { - self._rawValue = other._rawValue - } - - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal init?(@_nonEphemeral mutating other: UnsafePointer?) { - guard let unwrapped = other else { return nil } - self.init(mutating: unwrapped) - } - - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal init(@_nonEphemeral _ other: UnsafeMutablePointer) { - self._rawValue = other._rawValue - } - - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal init?(@_nonEphemeral _ other: UnsafeMutablePointer?) { - guard let unwrapped = other else { return nil } - self.init(unwrapped) - } -} - extension UnsafeMutablePointer where Pointee: ~Copyable { /// Allocates uninitialized memory for the specified number of instances of /// type `Pointee`. @@ -760,36 +685,9 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { /// /// - Parameter count: The amount of memory to allocate, counted in instances /// of `Pointee`. - @_alwaysEmitIntoClient - public static func allocate(capacity count: Int) - -> UnsafeMutablePointer { - let size = MemoryLayout.stride * count - // For any alignment <= _minAllocationAlignment, force alignment = 0. - // This forces the runtime's "aligned" allocation path so that - // deallocation does not require the original alignment. - // - // The runtime guarantees: - // - // align == 0 || align > _minAllocationAlignment: - // Runtime uses "aligned allocation". - // - // 0 < align <= _minAllocationAlignment: - // Runtime may use either malloc or "aligned allocation". - var align = Builtin.alignof(Pointee.self) - if Int(align) <= _minAllocationAlignment() { - align = (0)._builtinWordValue - } - let rawPtr = Builtin.allocRaw(size._builtinWordValue, align) - Builtin.bindMemory(rawPtr, count._builtinWordValue, Pointee.self) - return UnsafeMutablePointer(rawPtr) - } -} - -extension UnsafeMutablePointer { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal static func allocate( + @inlinable + @_preInverseGenerics + public static func allocate( capacity count: Int ) -> UnsafeMutablePointer { let size = MemoryLayout.stride * count @@ -817,9 +715,11 @@ extension UnsafeMutablePointer { extension UnsafeMutablePointer where Pointee: ~Copyable { /// Deallocates the memory block previously allocated at this pointer. /// - /// This pointer must be a pointer to the start of a previously allocated memory - /// block. The memory must not be initialized or `Pointee` must be a trivial type. - @_alwaysEmitIntoClient + /// This pointer must be a pointer to the start of a previously allocated + /// memory block. The memory must not be initialized or `Pointee` must be a + /// trivial type. + @inlinable + @_preInverseGenerics public func deallocate() { // Passing zero alignment to the runtime forces "aligned // deallocation". Since allocation via `UnsafeMutable[Raw][Buffer]Pointer` @@ -829,20 +729,6 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { } } -extension UnsafeMutablePointer { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal func deallocate() { - // Passing zero alignment to the runtime forces "aligned - // deallocation". Since allocation via `UnsafeMutable[Raw][Buffer]Pointer` - // always uses the "aligned allocation" path, this ensures that the - // runtime's allocation and deallocation paths are compatible. - Builtin.deallocRaw(_rawValue, (-1)._builtinWordValue, (0)._builtinWordValue) - } -} - - extension UnsafeMutablePointer where Pointee: ~Copyable { /// Reads or updates the instance referenced by this pointer. /// @@ -855,6 +741,7 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { /// using `pointee`. Instead, use an initializing method, such as /// `initialize(to:)`. @inlinable // unsafe-performance + @_preInverseGenerics public var pointee: Pointee { @_transparent unsafeAddress { return UnsafePointer(self) @@ -865,31 +752,18 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { } } -extension UnsafeMutablePointer { - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal var pointee: Pointee { - @_transparent unsafeAddress { - return UnsafePointer(self) - } - @_transparent nonmutating unsafeMutableAddress { - return self - } - } -} - extension UnsafeMutablePointer { /// Initializes this pointer's memory with the specified number of /// consecutive copies of the given value. /// /// The destination memory must be uninitialized or the pointer's `Pointee` - /// must be a trivial type. After a call to `initialize(repeating:count:)`, the - /// memory referenced by this pointer is initialized. + /// must be a trivial type. After a call to `initialize(repeating:count:)`, + /// the memory referenced by this pointer is initialized. /// /// - Parameters: /// - repeatedValue: The instance to initialize this pointer's memory with. /// - count: The number of consecutive copies of `newValue` to initialize. - /// `count` must not be negative. + /// `count` must not be negative. @inlinable public func initialize(repeating repeatedValue: Pointee, count: Int) { // FIXME: add tests (since the `count` has been added) @@ -923,7 +797,7 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { extension UnsafeMutablePointer { @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) @usableFromInline - internal func initialize(to value: Pointee) { // Note: `value` was __shared! + internal func initialize(to value: Pointee) { // Note: `value` is __shared! Builtin.initialize(value, self._rawValue) } } @@ -945,21 +819,13 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { /// `move()`, the memory is uninitialized. /// /// - Returns: The instance referenced by this pointer. - @_alwaysEmitIntoClient + @inlinable + @_preInverseGenerics public func move() -> Pointee { return Builtin.take(_rawValue) } } -extension UnsafeMutablePointer { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal func move() -> Pointee { - return Builtin.take(_rawValue) - } -} - extension UnsafeMutablePointer { /// Update this pointer's initialized memory with the specified number of /// consecutive copies of the given value. @@ -982,7 +848,6 @@ extension UnsafeMutablePointer { } } - @_alwaysEmitIntoClient @available(*, deprecated, renamed: "update(repeating:count:)") @_silgen_name("_swift_se0370_UnsafeMutablePointer_assign_repeating_count") @@ -1035,7 +900,6 @@ extension UnsafeMutablePointer { } } - @inlinable @_alwaysEmitIntoClient @available(*, deprecated, renamed: "update(from:count:)") @_silgen_name("_swift_se0370_UnsafeMutablePointer_assign_from_count") @@ -1064,6 +928,7 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { /// - count: The number of instances to move from `source` to this /// pointer's memory. `count` must not be negative. @_alwaysEmitIntoClient + @_preInverseGenerics public func moveInitialize( @_nonEphemeral from source: UnsafeMutablePointer, count: Int ) { @@ -1092,38 +957,6 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { } } -extension UnsafeMutablePointer { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal func moveInitialize( - @_nonEphemeral from source: UnsafeMutablePointer, count: Int - ) { - _debugPrecondition( - count >= 0, "UnsafeMutablePointer.moveInitialize with negative count") - if self < source || self >= source + count { - // initialize forward from a disjoint or following overlapping range. - Builtin.takeArrayFrontToBack( - Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue) - // This builtin is equivalent to: - // for i in 0..= 0, "UnsafeMutablePointer.moveUpdate(from:) with negative count") - _debugPrecondition( - self + count <= source || source + count <= self, - "moveUpdate overlapping range") - Builtin.assignTakeArray( - Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue) - // These builtins are equivalent to: - // for i in 0.. UnsafeMutableRawPointer { _debugPrecondition(count >= 0, "UnsafeMutablePointer.deinitialize with negative count") @@ -1249,21 +1064,7 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { } } -extension UnsafeMutablePointer { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal func deinitialize(count: Int) -> UnsafeMutableRawPointer { - _debugPrecondition(count >= 0, "UnsafeMutablePointer.deinitialize with negative count") - // TODO: IRGen optimization when `count` value is statically known to be 1, - // then call `Builtin.destroy(Pointee.self, _rawValue)` instead. - Builtin.destroyArray(Pointee.self, _rawValue, count._builtinWordValue) - return UnsafeMutableRawPointer(self) - } -} - -extension UnsafeMutablePointer /* where Pointee: ~Copyable */ { - // FIXME: We want this to have the constraint above, but that triggers a .swiftinterface issue. +extension UnsafeMutablePointer where Pointee: ~Copyable { /// Executes the given closure while temporarily binding memory to /// the specified number of instances of the given type. /// @@ -1324,8 +1125,6 @@ extension UnsafeMutablePointer /* where Pointee: ~Copyable */ { /// - pointer: The pointer temporarily bound to `T`. /// - Returns: The return value, if any, of the `body` closure parameter. @_alwaysEmitIntoClient - // This custom silgen name is chosen to not interfere with the old ABI - @_silgen_name("_swift_se0333_UnsafeMutablePointer_withMemoryRebound") public func withMemoryRebound( to type: T.Type, capacity count: Int, @@ -1348,10 +1147,9 @@ extension UnsafeMutablePointer /* where Pointee: ~Copyable */ { } extension UnsafeMutablePointer { - // This obsolete implementation uses the expected mangled name - // of `withMemoryRebound(to:capacity:_:)`, and provides - // an entry point for any binary linked against the stdlib binary - // for Swift 5.6 and older. + // This obsolete implementation uses the expected mangled name of + // `withMemoryRebound(to:capacity:_:)`, and provides an entry point + // for any binary linked against the stdlib binary for Swift 5.6 and older. @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) @_silgen_name("$sSp17withMemoryRebound2to8capacity_qd_0_qd__m_Siqd_0_Spyqd__GKXEtKr0_lF") @usableFromInline @@ -1380,7 +1178,8 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { /// /// - Parameter i: The offset from this pointer at which to access an /// instance, measured in strides of the pointer's `Pointee` type. - @_alwaysEmitIntoClient + @inlinable + @_preInverseGenerics public subscript(i: Int) -> Pointee { @_transparent unsafeAddress { @@ -1393,22 +1192,6 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { } } -extension UnsafeMutablePointer { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal subscript(i: Int) -> Pointee { - @_transparent - unsafeAddress { - return UnsafePointer(self + i) - } - @_transparent - nonmutating unsafeMutableAddress { - return self + i - } - } -} - extension UnsafeMutablePointer { /// Obtain a pointer to the stored property referred to by a key path. /// @@ -1418,7 +1201,6 @@ extension UnsafeMutablePointer { /// - Parameter property: A `KeyPath` whose `Root` is `Pointee`. /// - Returns: A pointer to the stored property represented /// by the key path, or `nil`. - @inlinable @_alwaysEmitIntoClient @_unavailableInEmbedded public func pointer( @@ -1441,7 +1223,6 @@ extension UnsafeMutablePointer { /// - Parameter property: A `WritableKeyPath` whose `Root` is `Pointee`. /// - Returns: A mutable pointer to the stored property represented /// by the key path, or `nil`. - @inlinable @_alwaysEmitIntoClient @_unavailableInEmbedded public func pointer( @@ -1455,16 +1236,14 @@ extension UnsafeMutablePointer { ) return .init(Builtin.gepRaw_Word(_rawValue, o._builtinWordValue)) } +} +extension UnsafeMutablePointer where Pointee: ~Copyable { @inlinable // unsafe-performance + @_preInverseGenerics internal static var _max: UnsafeMutablePointer { return UnsafeMutablePointer( bitPattern: 0 as Int &- MemoryLayout.stride )._unsafelyUnwrappedUnchecked } } - -@available(*, unavailable) -extension UnsafePointer: Sendable { } -@available(*, unavailable) -extension UnsafeMutablePointer: Sendable { } diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift index 2e016ff3fd935..2cc8d43c79a88 100644 --- a/stdlib/public/core/VarArgs.swift +++ b/stdlib/public/core/VarArgs.swift @@ -354,6 +354,7 @@ extension UnsafePointer: CVarArg where Pointee: ~Copyable { /// Transform `self` into a series of machine words that can be /// appropriately interpreted by C varargs. @inlinable // c-abi + @_preInverseGenerics public var _cVarArgEncoding: [Int] { return _encodeBitsAsWords(self) } @@ -363,6 +364,7 @@ extension UnsafeMutablePointer: CVarArg where Pointee: ~Copyable { /// Transform `self` into a series of machine words that can be /// appropriately interpreted by C varargs. @inlinable // c-abi + @_preInverseGenerics public var _cVarArgEncoding: [Int] { return _encodeBitsAsWords(self) } From 063758ab3ec06cd197a4c0976c18072d225110f7 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 6 Mar 2024 12:52:09 -0800 Subject: [PATCH 09/19] [stdlib] Optional: Adopt @_preInverseGenerics --- stdlib/public/core/Optional.swift | 109 +++++------------------------- 1 file changed, 17 insertions(+), 92 deletions(-) diff --git a/stdlib/public/core/Optional.swift b/stdlib/public/core/Optional.swift index aee4dea89b565..0c893b4a2e554 100644 --- a/stdlib/public/core/Optional.swift +++ b/stdlib/public/core/Optional.swift @@ -132,6 +132,10 @@ public enum Optional: ~Copyable { case some(Wrapped) } +extension Optional: Sendable where Wrapped: ~Copyable & Sendable { } + +extension Optional: _BitwiseCopyable where Wrapped: _BitwiseCopyable { } + extension Optional: Copyable /* where Wrapped: Copyable */ {} extension Optional: ExpressibleByNilLiteral where Wrapped: ~Copyable { @@ -145,6 +149,7 @@ extension Optional: ExpressibleByNilLiteral where Wrapped: ~Copyable { /// In this example, the assignment to the `i` variable calls this /// initializer behind the scenes. @_transparent + @_preInverseGenerics public init(nilLiteral: ()) { self = .none } @@ -152,18 +157,11 @@ extension Optional: ExpressibleByNilLiteral where Wrapped: ~Copyable { extension Optional where Wrapped: ~Copyable { /// Creates an instance that stores the given value. - @_alwaysEmitIntoClient @_transparent + @_preInverseGenerics public init(_ some: consuming Wrapped) { self = .some(some) } } -extension Optional { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal init(_ some: Wrapped) { self = .some(some) } -} - extension Optional { /// Evaluates the given closure when this `Optional` instance is not `nil`, /// passing the unwrapped value as a parameter. @@ -346,7 +344,6 @@ extension Optional { /// overhead for users, even in Debug builds. @inlinable internal var _unsafelyUnwrappedUnchecked: Wrapped { - // FIXME(NCG): Migrate to the function below and obsolete this. @inline(__always) get { if let x = self { @@ -358,12 +355,16 @@ extension Optional { } extension Optional where Wrapped: ~Copyable { + /// - Returns: `unsafelyUnwrapped`. + /// + /// This version is for internal stdlib use; it avoids any checking + /// overhead for users, even in Debug builds. @_alwaysEmitIntoClient - internal consuming func _unsafelyUnwrappedUnchecked2() -> Wrapped { + internal consuming func _consumingUncheckedUnwrapped() -> Wrapped { if let x = self { return x } - _internalInvariantFailure("_unsafelyUnwrappedUnchecked of nil optional") + _internalInvariantFailure("_uncheckedUnwrapped of nil optional") } } @@ -573,6 +574,7 @@ extension Optional where Wrapped: ~Copyable { /// - lhs: A `nil` literal. /// - rhs: A value to match against `nil`. @_transparent + @_preInverseGenerics public static func ~=( lhs: _OptionalNilComparisonType, rhs: borrowing Wrapped? @@ -610,6 +612,7 @@ extension Optional where Wrapped: ~Copyable { /// - lhs: A value to compare to `nil`. /// - rhs: A `nil` literal. @_transparent + @_preInverseGenerics public static func ==( lhs: borrowing Wrapped?, rhs: _OptionalNilComparisonType @@ -644,6 +647,7 @@ extension Optional where Wrapped: ~Copyable { /// - lhs: A value to compare to `nil`. /// - rhs: A `nil` literal. @_transparent + @_preInverseGenerics public static func !=( lhs: borrowing Wrapped?, rhs: _OptionalNilComparisonType @@ -678,6 +682,7 @@ extension Optional where Wrapped: ~Copyable { /// - lhs: A `nil` literal. /// - rhs: A value to compare to `nil`. @_transparent + @_preInverseGenerics public static func ==( lhs: _OptionalNilComparisonType, rhs: borrowing Wrapped? @@ -712,6 +717,7 @@ extension Optional where Wrapped: ~Copyable { /// - lhs: A `nil` literal. /// - rhs: A value to compare to `nil`. @_transparent + @_preInverseGenerics public static func !=( lhs: _OptionalNilComparisonType, rhs: borrowing Wrapped? @@ -724,83 +730,6 @@ extension Optional where Wrapped: ~Copyable { } } } - -extension Optional { - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal static func ~=( - lhs: _OptionalNilComparisonType, - rhs: Wrapped? - ) -> Bool { - switch rhs { - case .some: - return false - case .none: - return true - } - } - - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal static func ==( - lhs: Wrapped?, - rhs: _OptionalNilComparisonType - ) -> Bool { - switch lhs { - case .some: - return false - case .none: - return true - } - } - - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal static func !=( - lhs: Wrapped?, - rhs: _OptionalNilComparisonType - ) -> Bool { - switch lhs { - case .some: - return true - case .none: - return false - } - } - - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal static func ==( - lhs: _OptionalNilComparisonType, - rhs: Wrapped? - ) -> Bool { - switch rhs { - case .some: - return false - case .none: - return true - } - } - - // TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics - @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) - @usableFromInline - internal static func !=( - lhs: _OptionalNilComparisonType, - rhs: Wrapped? - ) -> Bool { - switch rhs { - case .some: - return true - case .none: - return false - } - } -} #else #error("FIXME(NCG): Fill this out.") #endif @@ -1013,7 +942,3 @@ extension Optional: _ObjectiveCBridgeable { } } #endif - -extension Optional: Sendable where Wrapped: ~Copyable & Sendable { } - -extension Optional: _BitwiseCopyable where Wrapped: _BitwiseCopyable { } From 3760c9b9056d0a79f196297ce032cd4f602cd317 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 6 Mar 2024 12:58:38 -0800 Subject: [PATCH 10/19] [stdlib] UnsafeRawPointer: Adopt @_preInverseGenerics --- stdlib/public/core/UnsafeRawPointer.swift | 68 +++++++++++------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/stdlib/public/core/UnsafeRawPointer.swift b/stdlib/public/core/UnsafeRawPointer.swift index 3e24ce8405b26..4586caec87e25 100644 --- a/stdlib/public/core/UnsafeRawPointer.swift +++ b/stdlib/public/core/UnsafeRawPointer.swift @@ -169,9 +169,9 @@ /// // Accessing 'numberPointer' is undefined behavior. @frozen public struct UnsafeRawPointer: _Pointer { - + public typealias Pointee = UInt8 - + /// The underlying raw pointer. /// Implements conformance to the public protocol `_Pointer`. public let _rawValue: Builtin.RawPointer @@ -189,27 +189,27 @@ extension UnsafeRawPointer: Sendable {} extension UnsafeRawPointer { /// Creates a new raw pointer from the given typed pointer. /// - /// Use this initializer to explicitly convert `other` to an `UnsafeRawPointer` - /// instance. This initializer creates a new pointer to the same address as - /// `other` and performs no allocation or copying. + /// Use this initializer to explicitly convert `other` to an + /// `UnsafeRawPointer` instance. This initializer creates a new pointer to the + /// same address as `other` and performs no allocation or copying. /// /// - Parameter other: The typed pointer to convert. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics public init(@_nonEphemeral _ other: UnsafePointer) { _rawValue = other._rawValue } /// Creates a new raw pointer from the given typed pointer. /// - /// Use this initializer to explicitly convert `other` to an `UnsafeRawPointer` - /// instance. This initializer creates a new pointer to the same address as - /// `other` and performs no allocation or copying. + /// Use this initializer to explicitly convert `other` to an + /// `UnsafeRawPointer` instance. This initializer creates a new pointer to the + /// same address as `other` and performs no allocation or copying. /// /// - Parameter other: The typed pointer to convert. If `other` is `nil`, the /// result is `nil`. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics public init?(@_nonEphemeral _ other: UnsafePointer?) { guard let unwrapped = other else { return nil } _rawValue = unwrapped._rawValue @@ -219,9 +219,9 @@ extension UnsafeRawPointer { extension UnsafeRawPointer { /// Creates a new raw pointer from the given mutable raw pointer. /// - /// Use this initializer to explicitly convert `other` to an `UnsafeRawPointer` - /// instance. This initializer creates a new pointer to the same address as - /// `other` and performs no allocation or copying. + /// Use this initializer to explicitly convert `other` to an + /// `UnsafeRawPointer` instance. This initializer creates a new pointer to the + /// same address as `other` and performs no allocation or copying. /// /// - Parameter other: The mutable raw pointer to convert. @_transparent @@ -231,9 +231,9 @@ extension UnsafeRawPointer { /// Creates a new raw pointer from the given mutable raw pointer. /// - /// Use this initializer to explicitly convert `other` to an `UnsafeRawPointer` - /// instance. This initializer creates a new pointer to the same address as - /// `other` and performs no allocation or copying. + /// Use this initializer to explicitly convert `other` to an + /// `UnsafeRawPointer` instance. This initializer creates a new pointer to the + /// same address as `other` and performs no allocation or copying. /// /// - Parameter other: The mutable raw pointer to convert. If `other` is /// `nil`, the result is `nil`. @@ -247,33 +247,34 @@ extension UnsafeRawPointer { extension UnsafeRawPointer { /// Creates a new raw pointer from the given typed pointer. /// - /// Use this initializer to explicitly convert `other` to an `UnsafeRawPointer` - /// instance. This initializer creates a new pointer to the same address as - /// `other` and performs no allocation or copying. + /// Use this initializer to explicitly convert `other` to an + /// `UnsafeRawPointer` instance. This initializer creates a new pointer to the + /// same address as `other` and performs no allocation or copying. /// /// - Parameter other: The typed pointer to convert. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics public init(@_nonEphemeral _ other: UnsafeMutablePointer) { _rawValue = other._rawValue } /// Creates a new raw pointer from the given typed pointer. /// - /// Use this initializer to explicitly convert `other` to an `UnsafeRawPointer` - /// instance. This initializer creates a new pointer to the same address as - /// `other` and performs no allocation or copying. + /// Use this initializer to explicitly convert `other` to an + /// `UnsafeRawPointer` instance. This initializer creates a new pointer to the + /// same address as `other` and performs no allocation or copying. /// /// - Parameter other: The typed pointer to convert. If `other` is `nil`, the /// result is `nil`. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics public init?(@_nonEphemeral _ other: UnsafeMutablePointer?) { guard let unwrapped = other else { return nil } _rawValue = unwrapped._rawValue } - /// Deallocates the previously allocated memory block referenced by this pointer. + /// Deallocates the previously allocated memory block referenced by this + /// pointer. /// /// The memory to be deallocated must be uninitialized or initialized to a /// trivial type. @@ -323,7 +324,7 @@ extension UnsafeRawPointer { /// The number of bytes in this region is /// `count * MemoryLayout.stride`. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics @discardableResult public func bindMemory( to type: T.Type, capacity count: Int @@ -410,7 +411,7 @@ extension UnsafeRawPointer { /// - Parameter to: The type `T` that the memory has already been bound to. /// - Returns: A typed pointer to the same memory as this raw pointer. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics public func assumingMemoryBound( to: T.Type ) -> UnsafePointer { @@ -620,8 +621,7 @@ extension UnsafeRawPointer { } } -/// A raw pointer for accessing and manipulating -/// untyped data. +/// A raw pointer for accessing and manipulating untyped data. /// /// The `UnsafeMutableRawPointer` type provides no automated memory management, /// no type safety, and no alignment guarantees. You are responsible for @@ -800,7 +800,7 @@ extension UnsafeMutableRawPointer { /// /// - Parameter other: The typed pointer to convert. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics public init(@_nonEphemeral _ other: UnsafeMutablePointer) { _rawValue = other._rawValue } @@ -814,7 +814,7 @@ extension UnsafeMutableRawPointer { /// - Parameter other: The typed pointer to convert. If `other` is `nil`, the /// result is `nil`. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics public init?(@_nonEphemeral _ other: UnsafeMutablePointer?) { guard let unwrapped = other else { return nil } _rawValue = unwrapped._rawValue @@ -937,7 +937,7 @@ extension UnsafeMutableRawPointer { /// The number of bytes in this region is /// `count * MemoryLayout.stride`. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics @discardableResult public func bindMemory( to type: T.Type, capacity count: Int @@ -1022,7 +1022,7 @@ extension UnsafeMutableRawPointer { /// - Parameter to: The type `T` that the memory has already been bound to. /// - Returns: A typed pointer to the same memory as this raw pointer. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics public func assumingMemoryBound( to: T.Type ) -> UnsafeMutablePointer { @@ -1216,7 +1216,7 @@ extension UnsafeMutableRawPointer { /// must not be negative. /// - Returns: A typed pointer to the memory referenced by this raw pointer. @inlinable - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics @discardableResult public func moveInitializeMemory( as type: T.Type, from source: UnsafeMutablePointer, count: Int From 47ce63ebd8d4d87a8872f231e6f59c4b21740f04 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 6 Mar 2024 13:00:06 -0800 Subject: [PATCH 11/19] [stdlib] OpaquePointer: Adopt @_preInverseGenerics --- stdlib/public/core/CTypes.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/public/core/CTypes.swift b/stdlib/public/core/CTypes.swift index 0b2206d405f0f..b3c2038672d76 100644 --- a/stdlib/public/core/CTypes.swift +++ b/stdlib/public/core/CTypes.swift @@ -182,7 +182,7 @@ extension OpaquePointer { extension OpaquePointer { /// Converts a typed `UnsafePointer` to an opaque C pointer. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics public init(@_nonEphemeral _ from: UnsafePointer) { self._rawValue = from._rawValue } @@ -191,7 +191,7 @@ extension OpaquePointer { /// /// The result is `nil` if `from` is `nil`. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics public init?(@_nonEphemeral _ from: UnsafePointer?) { guard let unwrapped = from else { return nil } self.init(unwrapped) @@ -201,7 +201,7 @@ extension OpaquePointer { extension OpaquePointer { /// Converts a typed `UnsafeMutablePointer` to an opaque C pointer. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics public init(@_nonEphemeral _ from: UnsafeMutablePointer) { self._rawValue = from._rawValue } @@ -210,7 +210,7 @@ extension OpaquePointer { /// /// The result is `nil` if `from` is `nil`. @_transparent - // FIXME(NCG): @_preInverseGenerics + @_preInverseGenerics public init?(@_nonEphemeral _ from: UnsafeMutablePointer?) { guard let unwrapped = from else { return nil } self.init(unwrapped) From 0441805ca8a0865d99a49c7ad985c926a1d655c9 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 6 Mar 2024 14:51:24 -0800 Subject: [PATCH 12/19] [stdlib] Generalize swap(_:_:) for noncopyable types --- stdlib/public/core/MutableCollection.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/public/core/MutableCollection.swift b/stdlib/public/core/MutableCollection.swift index 8fc77287cb114..687c3c07f7371 100644 --- a/stdlib/public/core/MutableCollection.swift +++ b/stdlib/public/core/MutableCollection.swift @@ -529,7 +529,8 @@ extension MutableCollection { /// - a: The first value to swap. /// - b: The second value to swap. @inlinable -public func swap(_ a: inout T, _ b: inout T) { +@_preInverseGenerics +public func swap(_ a: inout T, _ b: inout T) { // Semantically equivalent to (a, b) = (b, a). // Microoptimized to avoid retain/release traffic. #if $BuiltinUnprotectedAddressOf From cdc3f3d2d7137c65538387ee5114ad15aa573fc7 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 6 Mar 2024 17:42:14 -0800 Subject: [PATCH 13/19] [stdlib] UnsafePointer: Add @_preInverseGenerics to stored properties --- stdlib/public/core/UnsafePointer.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stdlib/public/core/UnsafePointer.swift b/stdlib/public/core/UnsafePointer.swift index a1331b9c13166..71ab98ff37098 100644 --- a/stdlib/public/core/UnsafePointer.swift +++ b/stdlib/public/core/UnsafePointer.swift @@ -210,6 +210,7 @@ public struct UnsafePointer: _Pointer, Copyable { public typealias Distance = Int /// The underlying raw (untyped) pointer. + @_preInverseGenerics public let _rawValue: Builtin.RawPointer /// Creates an `UnsafePointer` from a builtin raw pointer. @@ -602,6 +603,7 @@ public struct UnsafeMutablePointer: _Pointer, Copyable { public typealias Distance = Int /// The underlying raw (untyped) pointer. + @_preInverseGenerics public let _rawValue: Builtin.RawPointer /// Creates an `UnsafeMutablePointer` from a builtin raw pointer. From af5ab90f0371a799ddb81e47ee48e427a5495c7f Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 6 Mar 2024 18:04:23 -0800 Subject: [PATCH 14/19] [stdlib] UnsafePointer: Add @_preInverseGenerics to _Pointer conformance --- stdlib/public/core/UnsafePointer.swift | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/stdlib/public/core/UnsafePointer.swift b/stdlib/public/core/UnsafePointer.swift index 71ab98ff37098..9d5cf2765ec34 100644 --- a/stdlib/public/core/UnsafePointer.swift +++ b/stdlib/public/core/UnsafePointer.swift @@ -204,10 +204,7 @@ /// let numberPointer = UnsafePointer(&number) /// // Accessing 'numberPointer' is undefined behavior. @frozen // unsafe-performance -public struct UnsafePointer: _Pointer, Copyable { - - /// A type that represents the distance between two pointers. - public typealias Distance = Int +public struct UnsafePointer: Copyable { /// The underlying raw (untyped) pointer. @_preInverseGenerics @@ -224,6 +221,12 @@ public struct UnsafePointer: _Pointer, Copyable { @available(*, unavailable) extension UnsafePointer: Sendable where Pointee: ~Copyable {} +@_preInverseGenerics +extension UnsafePointer: _Pointer where Pointee: ~Copyable { + /// A type that represents the distance between two pointers. + public typealias Distance = Int +} + extension UnsafePointer where Pointee: ~Copyable { /// Deallocates the memory block previously allocated at this pointer. /// @@ -597,11 +600,7 @@ extension UnsafePointer where Pointee: ~Copyable { /// let numberPointer = UnsafeMutablePointer(&number) /// // Accessing 'numberPointer' is undefined behavior. @frozen // unsafe-performance -public struct UnsafeMutablePointer: _Pointer, Copyable { - - /// A type that represents the distance between two pointers. - public typealias Distance = Int - +public struct UnsafeMutablePointer: Copyable { /// The underlying raw (untyped) pointer. @_preInverseGenerics public let _rawValue: Builtin.RawPointer @@ -617,6 +616,12 @@ public struct UnsafeMutablePointer: _Pointer, Copyable { @available(*, unavailable) extension UnsafeMutablePointer: Sendable where Pointee: ~Copyable {} +@_preInverseGenerics +extension UnsafeMutablePointer: _Pointer where Pointee: ~Copyable { + /// A type that represents the distance between two pointers. + public typealias Distance = Int +} + extension UnsafeMutablePointer where Pointee: ~Copyable { /// Creates a mutable typed pointer referencing the same memory as the given /// immutable pointer. From d60387a8bf2c927c3c5c5fe4934f61a33456d264 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 6 Mar 2024 18:04:37 -0800 Subject: [PATCH 15/19] [stdlib] Optional: Add @_preInverseGenerics to ExpressibleByNilLiteral conformance --- stdlib/public/core/Optional.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/public/core/Optional.swift b/stdlib/public/core/Optional.swift index 0c893b4a2e554..dad9178ebe410 100644 --- a/stdlib/public/core/Optional.swift +++ b/stdlib/public/core/Optional.swift @@ -138,6 +138,7 @@ extension Optional: _BitwiseCopyable where Wrapped: _BitwiseCopyable { } extension Optional: Copyable /* where Wrapped: Copyable */ {} +@_preInverseGenerics extension Optional: ExpressibleByNilLiteral where Wrapped: ~Copyable { /// Creates an instance initialized with `nil`. /// From 3ea98dcdaebba01b2b711e6f12e641b0822d45db Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 6 Mar 2024 18:40:24 -0800 Subject: [PATCH 16/19] =?UTF-8?q?[stdlib]=20UnsafePointer:=20Don=E2=80=99t?= =?UTF-8?q?=20let=20the=20compiler=20synthesize=20`hashValue`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- stdlib/public/core/UnsafePointer.swift | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/stdlib/public/core/UnsafePointer.swift b/stdlib/public/core/UnsafePointer.swift index 9d5cf2765ec34..3a65dec8d1902 100644 --- a/stdlib/public/core/UnsafePointer.swift +++ b/stdlib/public/core/UnsafePointer.swift @@ -227,6 +227,15 @@ extension UnsafePointer: _Pointer where Pointee: ~Copyable { public typealias Distance = Int } +extension UnsafePointer { + // Note: This explicit `hashValue` applies @_preInverseGenerics to the + // original (pre-6.0) compiler-synthesized version. + @_preInverseGenerics + public var hashValue: Int { + _hashValue(for: self) + } +} + extension UnsafePointer where Pointee: ~Copyable { /// Deallocates the memory block previously allocated at this pointer. /// @@ -668,6 +677,15 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { } } +extension UnsafeMutablePointer { + // Note: This explicit `hashValue` applies @_preInverseGenerics to the + // original (pre-6.0) compiler-synthesized version. + @_preInverseGenerics + public var hashValue: Int { + _hashValue(for: self) + } +} + extension UnsafeMutablePointer where Pointee: ~Copyable { /// Allocates uninitialized memory for the specified number of instances of /// type `Pointee`. From 9b3dec7c474bd02806abc66fff32f1dc58a00854 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Wed, 6 Mar 2024 20:05:21 -0800 Subject: [PATCH 17/19] [stdlib] UnsafePointer: Resolve most of the symbol mismatches --- stdlib/public/core/UnsafePointer.swift | 131 +++++++++++++++++++++---- stdlib/public/core/VarArgs.swift | 2 + 2 files changed, 113 insertions(+), 20 deletions(-) diff --git a/stdlib/public/core/UnsafePointer.swift b/stdlib/public/core/UnsafePointer.swift index 3a65dec8d1902..bbd94ac7852da 100644 --- a/stdlib/public/core/UnsafePointer.swift +++ b/stdlib/public/core/UnsafePointer.swift @@ -227,14 +227,30 @@ extension UnsafePointer: _Pointer where Pointee: ~Copyable { public typealias Distance = Int } -extension UnsafePointer { - // Note: This explicit `hashValue` applies @_preInverseGenerics to the +@_preInverseGenerics +extension UnsafePointer: Equatable where Pointee: ~Copyable {} +@_preInverseGenerics +extension UnsafePointer: Hashable where Pointee: ~Copyable { + // Note: This explicit `hashValue` applies @_preInverseGenerics to emulate the // original (pre-6.0) compiler-synthesized version. @_preInverseGenerics public var hashValue: Int { _hashValue(for: self) } } +@_preInverseGenerics +extension UnsafePointer: Comparable where Pointee: ~Copyable {} +@_preInverseGenerics +extension UnsafePointer: Strideable where Pointee: ~Copyable {} +#if !$Embedded +@_preInverseGenerics +extension UnsafePointer: CustomDebugStringConvertible +where Pointee: ~Copyable {} +#endif +#if SWIFT_ENABLE_REFLECTION +@_preInverseGenerics +extension UnsafePointer: CustomReflectable where Pointee: ~Copyable {} +#endif extension UnsafePointer where Pointee: ~Copyable { /// Deallocates the memory block previously allocated at this pointer. @@ -258,8 +274,7 @@ extension UnsafePointer where Pointee: ~Copyable { /// /// When reading from the `pointee` property, the instance referenced by /// this pointer must already be initialized. - @inlinable - @_preInverseGenerics + @_alwaysEmitIntoClient public var pointee: Pointee { @_transparent unsafeAddress { return self @@ -267,6 +282,19 @@ extension UnsafePointer where Pointee: ~Copyable { } } +extension UnsafePointer { + // This preserves the ABI of the original (pre-6.0) `pointee` property that + // used to export a getter. The current one above would export a read + // accessor, if it wasn't @_alwaysEmitIntoClient. + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal var pointee: Pointee { + @_transparent unsafeAddress { + return self + } + } +} + extension UnsafePointer where Pointee: ~Copyable { /// Accesses the pointee at the specified offset from this pointer. /// @@ -275,8 +303,7 @@ extension UnsafePointer where Pointee: ~Copyable { /// /// - Parameter i: The offset from this pointer at which to access an /// instance, measured in strides of the pointer's `Pointee` type. - @inlinable - @_preInverseGenerics + @_alwaysEmitIntoClient public subscript(i: Int) -> Pointee { @_transparent unsafeAddress { @@ -285,6 +312,20 @@ extension UnsafePointer where Pointee: ~Copyable { } } +extension UnsafePointer { + // This preserves the ABI of the original (pre-6.0) subscript that used to + // export a getter. The current one above would export a read accessor, if it + // wasn't @_alwaysEmitIntoClient. + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal subscript(i: Int) -> Pointee { + @_transparent + unsafeAddress { + return self + i + } + } +} + extension UnsafePointer where Pointee: ~Copyable { /// Executes the given closure while temporarily binding memory to /// the specified number of instances of type `T`. @@ -631,6 +672,31 @@ extension UnsafeMutablePointer: _Pointer where Pointee: ~Copyable { public typealias Distance = Int } +@_preInverseGenerics +extension UnsafeMutablePointer: Equatable where Pointee: ~Copyable {} +@_preInverseGenerics +extension UnsafeMutablePointer: Hashable where Pointee: ~Copyable { + // Note: This explicit `hashValue` applies @_preInverseGenerics to emulate the + // original (pre-6.0) compiler-synthesized version. + @_preInverseGenerics + public var hashValue: Int { + _hashValue(for: self) + } +} +@_preInverseGenerics +extension UnsafeMutablePointer: Comparable where Pointee: ~Copyable {} +@_preInverseGenerics +extension UnsafeMutablePointer: Strideable where Pointee: ~Copyable {} +#if !$Embedded +@_preInverseGenerics +extension UnsafeMutablePointer: CustomDebugStringConvertible +where Pointee: ~Copyable {} +#endif +#if SWIFT_ENABLE_REFLECTION +@_preInverseGenerics +extension UnsafeMutablePointer: CustomReflectable where Pointee: ~Copyable {} +#endif + extension UnsafeMutablePointer where Pointee: ~Copyable { /// Creates a mutable typed pointer referencing the same memory as the given /// immutable pointer. @@ -677,15 +743,6 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { } } -extension UnsafeMutablePointer { - // Note: This explicit `hashValue` applies @_preInverseGenerics to the - // original (pre-6.0) compiler-synthesized version. - @_preInverseGenerics - public var hashValue: Int { - _hashValue(for: self) - } -} - extension UnsafeMutablePointer where Pointee: ~Copyable { /// Allocates uninitialized memory for the specified number of instances of /// type `Pointee`. @@ -765,8 +822,7 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { /// Uninitialized memory cannot be initialized to a nontrivial type /// using `pointee`. Instead, use an initializing method, such as /// `initialize(to:)`. - @inlinable // unsafe-performance - @_preInverseGenerics + @_alwaysEmitIntoClient public var pointee: Pointee { @_transparent unsafeAddress { return UnsafePointer(self) @@ -777,6 +833,23 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { } } +extension UnsafeMutablePointer { + // This preserves the ABI of the original (pre-6.0) `pointee` property that + // used to export a getter. The current one above would export a read + // accessor, if it wasn't @_alwaysEmitIntoClient. + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal var pointee: Pointee { + @_transparent unsafeAddress { + return UnsafePointer(self) + } + @_transparent nonmutating unsafeMutableAddress { + return self + } + } +} + + extension UnsafeMutablePointer { /// Initializes this pointer's memory with the specified number of /// consecutive copies of the given value. @@ -952,7 +1025,7 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { /// referenced by `source` and this pointer may overlap. /// - count: The number of instances to move from `source` to this /// pointer's memory. `count` must not be negative. - @_alwaysEmitIntoClient + @inlinable @_preInverseGenerics public func moveInitialize( @_nonEphemeral from source: UnsafeMutablePointer, count: Int @@ -1036,6 +1109,7 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { /// - count: The number of instances to move from `source` to this /// pointer's memory. `count` must not be negative. @inlinable + @_silgen_name("$sSp10moveAssign4from5countySpyxG_SitF") @_preInverseGenerics public func moveUpdate( @_nonEphemeral from source: UnsafeMutablePointer, count: Int @@ -1203,8 +1277,7 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { /// /// - Parameter i: The offset from this pointer at which to access an /// instance, measured in strides of the pointer's `Pointee` type. - @inlinable - @_preInverseGenerics + @_alwaysEmitIntoClient public subscript(i: Int) -> Pointee { @_transparent unsafeAddress { @@ -1217,6 +1290,24 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { } } +extension UnsafeMutablePointer { + // This preserves the ABI of the original (pre-6.0) subscript that used to + // export a getter. The current one above would export a read accessor, if it + // wasn't @_alwaysEmitIntoClient. + @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2) + @usableFromInline + internal subscript(i: Int) -> Pointee { + @_transparent + unsafeAddress { + return UnsafePointer(self + i) + } + @_transparent + nonmutating unsafeMutableAddress { + return self + i + } + } +} + extension UnsafeMutablePointer { /// Obtain a pointer to the stored property referred to by a key path. /// diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift index 2cc8d43c79a88..88ce9aef25f9a 100644 --- a/stdlib/public/core/VarArgs.swift +++ b/stdlib/public/core/VarArgs.swift @@ -350,6 +350,7 @@ extension OpaquePointer: CVarArg { } } +@_preInverseGenerics extension UnsafePointer: CVarArg where Pointee: ~Copyable { /// Transform `self` into a series of machine words that can be /// appropriately interpreted by C varargs. @@ -360,6 +361,7 @@ extension UnsafePointer: CVarArg where Pointee: ~Copyable { } } +@_preInverseGenerics extension UnsafeMutablePointer: CVarArg where Pointee: ~Copyable { /// Transform `self` into a series of machine words that can be /// appropriately interpreted by C varargs. From fb8407110fcfadd009d8d063063ebd758e46f59c Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Thu, 7 Mar 2024 14:18:13 -0800 Subject: [PATCH 18/19] [Synchronization] Update symbol expectations --- test/abi/macOS/arm64/synchronization.swift | 49 +++++++++++----------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/test/abi/macOS/arm64/synchronization.swift b/test/abi/macOS/arm64/synchronization.swift index 39119520a99de..3994cbb8417e4 100644 --- a/test/abi/macOS/arm64/synchronization.swift +++ b/test/abi/macOS/arm64/synchronization.swift @@ -449,18 +449,6 @@ Added: _$sSO15Synchronization27AtomicOptionalRepresentableAAMc // protocol witness table for Swift.ObjectIdentifier : Synchronization.AtomicOptionalRepresentable in Synchronization Added: _$sSO15Synchronization27AtomicOptionalRepresentableAAWP -// protocol conformance descriptor for Swift.UnsafePointer : Synchronization.AtomicRepresentable in Synchronization -Added: _$sSPyxG15Synchronization19AtomicRepresentableABMc - -// protocol witness table for Swift.UnsafePointer : Synchronization.AtomicRepresentable in Synchronization -Added: _$sSPyxG15Synchronization19AtomicRepresentableABWP - -// protocol conformance descriptor for Swift.UnsafePointer : Synchronization.AtomicOptionalRepresentable in Synchronization -Added: _$sSPyxG15Synchronization27AtomicOptionalRepresentableABMc - -// protocol witness table for Swift.UnsafePointer : Synchronization.AtomicOptionalRepresentable in Synchronization -Added: _$sSPyxG15Synchronization27AtomicOptionalRepresentableABWP - // protocol conformance descriptor for Swift.UnsafeBufferPointer : Synchronization.AtomicRepresentable in Synchronization Added: _$sSRyxG15Synchronization19AtomicRepresentableABMc @@ -509,18 +497,6 @@ Added: _$sSi15Synchronization19AtomicRepresentableAAMc // protocol witness table for Swift.Int : Synchronization.AtomicRepresentable in Synchronization Added: _$sSi15Synchronization19AtomicRepresentableAAWP -// protocol conformance descriptor for Swift.UnsafeMutablePointer : Synchronization.AtomicRepresentable in Synchronization -Added: _$sSpyxG15Synchronization19AtomicRepresentableABMc - -// protocol witness table for Swift.UnsafeMutablePointer : Synchronization.AtomicRepresentable in Synchronization -Added: _$sSpyxG15Synchronization19AtomicRepresentableABWP - -// protocol conformance descriptor for Swift.UnsafeMutablePointer : Synchronization.AtomicOptionalRepresentable in Synchronization -Added: _$sSpyxG15Synchronization27AtomicOptionalRepresentableABMc - -// protocol witness table for Swift.UnsafeMutablePointer : Synchronization.AtomicOptionalRepresentable in Synchronization -Added: _$sSpyxG15Synchronization27AtomicOptionalRepresentableABWP - // protocol conformance descriptor for Swift.UnsafeMutableBufferPointer : Synchronization.AtomicRepresentable in Synchronization Added: _$sSryxG15Synchronization19AtomicRepresentableABMc @@ -643,3 +619,28 @@ Added: _$ss9UnmanagedVyxG15Synchronization27AtomicOptionalRepresentableADWP // protocol conformance descriptor for A? : Synchronization.AtomicRepresentable in Synchronization Added: _$sxSg15Synchronization19AtomicRepresentableA2B0b8OptionalC0RzlMc + +// protocol conformance descriptor for < where A: ~Swift.Copyable> Swift.UnsafePointer : Synchronization.AtomicRepresentable in Synchronization +Added: _$sSPyxG15Synchronization19AtomicRepresentableABRiczrlMc + +// protocol witness table for < where A: ~Swift.Copyable> Swift.UnsafePointer : Synchronization.AtomicRepresentable in Synchronization +Added: _$sSPyxG15Synchronization19AtomicRepresentableABRiczrlWP + +// protocol conformance descriptor for < where A: ~Swift.Copyable> Swift.UnsafePointer : Synchronization.AtomicOptionalRepresentable in Synchronization +Added: _$sSPyxG15Synchronization27AtomicOptionalRepresentableABRiczrlMc + +// protocol witness table for < where A: ~Swift.Copyable> Swift.UnsafePointer : Synchronization.AtomicOptionalRepresentable in Synchronization +Added: _$sSPyxG15Synchronization27AtomicOptionalRepresentableABRiczrlWP + +// protocol conformance descriptor for < where A: ~Swift.Copyable> Swift.UnsafeMutablePointer : Synchronization.AtomicRepresentable in Synchronization +Added: _$sSpyxG15Synchronization19AtomicRepresentableABRiczrlMc + +// protocol witness table for < where A: ~Swift.Copyable> Swift.UnsafeMutablePointer : Synchronization.AtomicRepresentable in Synchronization +Added: _$sSpyxG15Synchronization19AtomicRepresentableABRiczrlWP + +// protocol conformance descriptor for < where A: ~Swift.Copyable> Swift.UnsafeMutablePointer : Synchronization.AtomicOptionalRepresentable in Synchronization +Added: _$sSpyxG15Synchronization27AtomicOptionalRepresentableABRiczrlMc + +// protocol witness table for < where A: ~Swift.Copyable> Swift.UnsafeMutablePointer : Synchronization.AtomicOptionalRepresentable in Synchronization +Added: _$sSpyxG15Synchronization27AtomicOptionalRepresentableABRiczrlWP + From 817642a377dda0374b1cab35f8422bc23a4083c5 Mon Sep 17 00:00:00 2001 From: Ben Cohen Date: Sun, 17 Mar 2024 10:15:15 -0700 Subject: [PATCH 19/19] fix typo in benchmarks cmake --- benchmark/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index 9d5b4a13314e9..f6cd26826801f 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -218,7 +218,7 @@ set(SWIFT_BENCH_MODULES_DISABLED set(SWIFT_MULTISOURCE_SWIFT_BENCHES) # FIXME(NCG): Temporarily disabled -set(SWIFT_MULTISOURCE_SWIFT_BENCHES_DISABLED) +set(SWIFT_MULTISOURCE_SWIFT_BENCHES_DISABLED multi-source/PrimsSplit )