Skip to content

Restrict withUnsafeBytes to swift 5.0 or greater availability to avoid ambiguity #21679

New issue

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

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

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 35 additions & 12 deletions stdlib/public/Darwin/Foundation/ContiguousBytes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,64 +21,87 @@ public protocol ContiguousBytes {
/// the same buffer pointer will be passed in every time.
/// - warning: The buffer argument to the body should not be stored or used
/// outside of the lifetime of the call to the closure.
func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R
func withContiguousUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R
}

extension Data {
@inlinable
@available(swift, introduced: 5)
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
return try withContiguousUnsafeBytes(body)
}
}

//===--- Collection Conformances ------------------------------------------===//

// FIXME: When possible, expand conformance to `where Element : Trivial`.
extension Array : ContiguousBytes where Element == UInt8 { }
extension Array : ContiguousBytes where Element == UInt8 {
@inlinable
public func withContiguousUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
return try withUnsafeBytes(body)
}
}

// FIXME: When possible, expand conformance to `where Element : Trivial`.
extension ArraySlice : ContiguousBytes where Element == UInt8 { }
extension ArraySlice : ContiguousBytes where Element == UInt8 {
@inlinable
public func withContiguousUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
return try withUnsafeBytes(body)
}
}

// FIXME: When possible, expand conformance to `where Element : Trivial`.
extension ContiguousArray : ContiguousBytes where Element == UInt8 { }
extension ContiguousArray : ContiguousBytes where Element == UInt8 {
@inlinable
public func withContiguousUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
return try withUnsafeBytes(body)
}
}

//===--- Pointer Conformances ---------------------------------------------===//

extension UnsafeRawBufferPointer : ContiguousBytes {
@inlinable
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
public func withContiguousUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
return try body(self)
}
}

extension UnsafeMutableRawBufferPointer : ContiguousBytes {
@inlinable
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
public func withContiguousUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
return try body(UnsafeRawBufferPointer(self))
}
}

// FIXME: When possible, expand conformance to `where Element : Trivial`.
extension UnsafeBufferPointer : ContiguousBytes where Element == UInt8 {
@inlinable
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
public func withContiguousUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
return try body(UnsafeRawBufferPointer(self))
}
}

// FIXME: When possible, expand conformance to `where Element : Trivial`.
extension UnsafeMutableBufferPointer : ContiguousBytes where Element == UInt8 {
@inlinable
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
public func withContiguousUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
return try body(UnsafeRawBufferPointer(self))
}
}

// FIXME: When possible, expand conformance to `where Element : Trivial`.
extension EmptyCollection : ContiguousBytes where Element == UInt8 {
@inlinable
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
public func withContiguousUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
return try body(UnsafeRawBufferPointer(start: nil, count: 0))
}
}

// FIXME: When possible, expand conformance to `where Element : Trivial`.
extension CollectionOfOne : ContiguousBytes where Element == UInt8 {
@inlinable
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
public func withContiguousUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
let element = self.first!
return try Swift.withUnsafeBytes(of: element) {
return try body($0)
Expand All @@ -89,9 +112,9 @@ extension CollectionOfOne : ContiguousBytes where Element == UInt8 {
//===--- Conditional Conformances -----------------------------------------===//

extension Slice : ContiguousBytes where Base : ContiguousBytes {
public func withUnsafeBytes<ResultType>(_ body: (UnsafeRawBufferPointer) throws -> ResultType) rethrows -> ResultType {
public func withContiguousUnsafeBytes<ResultType>(_ body: (UnsafeRawBufferPointer) throws -> ResultType) rethrows -> ResultType {
let offset = base.distance(from: base.startIndex, to: self.startIndex)
return try base.withUnsafeBytes { ptr in
return try base.withContiguousUnsafeBytes { ptr in
let slicePtr = ptr.baseAddress?.advanced(by: offset)
let sliceBuffer = UnsafeRawBufferPointer(start: slicePtr, count: self.count)
return try body(sliceBuffer)
Expand Down
42 changes: 21 additions & 21 deletions stdlib/public/Darwin/Foundation/Data.swift
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,9 @@ internal final class _DataStorage {
@inlinable
func append(_ otherData: Data) {
guard otherData.count > 0 else { return }
otherData.withUnsafeBytes {
append($0.baseAddress!, length: $0.count)
}
otherData.withContiguousUnsafeBytes {
append($0.baseAddress!, length: $0.count)
}
}

@inlinable
Expand Down Expand Up @@ -1950,7 +1950,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
@inlinable
public init(repeating repeatedValue: UInt8, count: Int) {
self.init(count: count)
withUnsafeMutableBytes { (buffer: UnsafeMutableRawBufferPointer) -> Void in
withContiguousUnsafeMutableBytes { (buffer: UnsafeMutableRawBufferPointer) -> Void in
memset(buffer.baseAddress, Int32(repeatedValue), buffer.count)
}
}
Expand Down Expand Up @@ -2074,7 +2074,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
public init<S: Sequence>(_ elements: S) where S.Element == UInt8 {
// If the sequence is already contiguous, access the underlying raw memory directly.
if let contiguous = elements as? ContiguousBytes {
_representation = contiguous.withUnsafeBytes { return _Representation($0) }
_representation = contiguous.withContiguousUnsafeBytes { return _Representation($0) }
return
}

Expand Down Expand Up @@ -2161,31 +2161,31 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
/// Access the bytes in the data.
///
/// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure.
@available(swift, deprecated: 5, message: "use `withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R` instead")
@available(swift, deprecated: 5, message: "use `withContiguousUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R` instead")
public func withUnsafeBytes<ResultType, ContentType>(_ body: (UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType {
return try _representation.withUnsafeBytes {
return try body($0.baseAddress?.assumingMemoryBound(to: ContentType.self) ?? UnsafePointer<ContentType>(bitPattern: 0xBAD0)!)
}
}

@inlinable
public func withUnsafeBytes<ResultType>(_ body: (UnsafeRawBufferPointer) throws -> ResultType) rethrows -> ResultType {
public func withContiguousUnsafeBytes<ResultType>(_ body: (UnsafeRawBufferPointer) throws -> ResultType) rethrows -> ResultType {
return try _representation.withUnsafeBytes(body)
}

/// Mutate the bytes in the data.
///
/// This function assumes that you are mutating the contents.
/// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure.
@available(swift, deprecated: 5, message: "use `withUnsafeMutableBytes<R>(_: (UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R` instead")
@available(swift, deprecated: 5, message: "use `withContiguousUnsafeMutableBytes<R>(_: (UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R` instead")
public mutating func withUnsafeMutableBytes<ResultType, ContentType>(_ body: (UnsafeMutablePointer<ContentType>) throws -> ResultType) rethrows -> ResultType {
return try _representation.withUnsafeMutableBytes {
return try body($0.baseAddress?.assumingMemoryBound(to: ContentType.self) ?? UnsafeMutablePointer<ContentType>(bitPattern: 0xBAD0)!)
}
}

@inlinable
public mutating func withUnsafeMutableBytes<ResultType>(_ body: (UnsafeMutableRawBufferPointer) throws -> ResultType) rethrows -> ResultType {
public mutating func withContiguousUnsafeMutableBytes<ResultType>(_ body: (UnsafeMutableRawBufferPointer) throws -> ResultType) rethrows -> ResultType {
return try _representation.withUnsafeMutableBytes(body)
}

Expand Down Expand Up @@ -2334,7 +2334,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
@inlinable
public mutating func append(_ other: Data) {
guard other.count > 0 else { return }
other.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) in
other.withContiguousUnsafeBytes { (buffer: UnsafeRawBufferPointer) in
_representation.append(contentsOf: buffer)
}
}
Expand All @@ -2358,7 +2358,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
public mutating func append<S: Sequence>(contentsOf elements: S) where S.Element == Element {
// If the sequence is already contiguous, access the underlying raw memory directly.
if let contiguous = elements as? ContiguousBytes {
contiguous.withUnsafeBytes {
contiguous.withContiguousUnsafeBytes {
_representation.append(contentsOf: $0)
}

Expand Down Expand Up @@ -2420,7 +2420,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
/// - parameter data: The replacement data.
@inlinable
public mutating func replaceSubrange(_ subrange: Range<Index>, with data: Data) {
data.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) in
data.withContiguousUnsafeBytes { (buffer: UnsafeRawBufferPointer) in
_representation.replaceSubrange(subrange, with: buffer.baseAddress, count: buffer.count)
}
}
Expand Down Expand Up @@ -2474,7 +2474,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
}
let slice = self[range]

return slice.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) -> Data in
return slice.withContiguousUnsafeBytes { (buffer: UnsafeRawBufferPointer) -> Data in
return Data(bytes: buffer.baseAddress!, count: buffer.count)
}
}
Expand Down Expand Up @@ -2517,7 +2517,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
public func advanced(by amount: Int) -> Data {
let length = count - amount
precondition(length > 0)
return withUnsafeBytes { (ptr: UnsafeRawBufferPointer) -> Data in
return withContiguousUnsafeBytes { (ptr: UnsafeRawBufferPointer) -> Data in
return Data(bytes: ptr.baseAddress!.advanced(by: amount), count: length)
}
}
Expand Down Expand Up @@ -2612,7 +2612,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
guard !isEmpty else { return (makeIterator(), buffer.startIndex) }
let cnt = Swift.min(count, buffer.count)

withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
withContiguousUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
_ = memcpy(UnsafeMutableRawPointer(buffer.baseAddress), bytes.baseAddress, cnt)
}

Expand Down Expand Up @@ -2693,10 +2693,10 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
set { fatalError() }
}

@available(*, unavailable, message: "use withUnsafeBytes instead")
@available(*, unavailable, message: "use withContiguousUnsafeBytes instead")
public var bytes: UnsafeRawPointer { fatalError() }

@available(*, unavailable, message: "use withUnsafeMutableBytes instead")
@available(*, unavailable, message: "use withContiguousUnsafeMutableBytes instead")
public var mutableBytes: UnsafeMutableRawPointer { fatalError() }

/// Returns `true` if the two `Data` arguments are equal.
Expand All @@ -2707,8 +2707,8 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
return false
}
if length1 > 0 {
return d1.withUnsafeBytes { (b1: UnsafeRawBufferPointer) in
return d2.withUnsafeBytes { (b2: UnsafeRawBufferPointer) in
return d1.withContiguousUnsafeBytes { (b1: UnsafeRawBufferPointer) in
return d2.withContiguousUnsafeBytes { (b2: UnsafeRawBufferPointer) in
return memcmp(b1.baseAddress!, b2.baseAddress!, b2.count) == 0
}
}
Expand All @@ -2734,7 +2734,7 @@ extension Data : CustomStringConvertible, CustomDebugStringConvertible, CustomRe
var children: [(label: String?, value: Any)] = []
children.append((label: "count", value: nBytes))

self.withUnsafeBytes { (bytes : UnsafeRawBufferPointer) in
withContiguousUnsafeBytes { (bytes : UnsafeRawBufferPointer) in
children.append((label: "pointer", value: bytes.baseAddress!))
}

Expand Down Expand Up @@ -2816,7 +2816,7 @@ extension Data : Codable {

public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try withUnsafeBytes { (buffer: UnsafeRawBufferPointer) in
try withContiguousUnsafeBytes { (buffer: UnsafeRawBufferPointer) in
try container.encode(contentsOf: buffer)
}
}
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/Darwin/Foundation/DataProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ extension DataProtocol {
break
}

region.withUnsafeBytes { buffer in
region.withContiguousUnsafeBytes { buffer in
let offsetPtr = UnsafeMutableRawBufferPointer(rebasing: ptr[offset...])
let buf = UnsafeRawBufferPointer(start: buffer.baseAddress, count: Swift.min(buffer.count, amountToCopy))
offsetPtr.copyMemory(from: buf)
Expand Down Expand Up @@ -206,7 +206,7 @@ extension DataProtocol where Self : ContiguousBytes {
precondition(ptr.baseAddress != nil)

let concreteRange = range.relative(to: self)
withUnsafeBytes { fullBuffer in
withContiguousUnsafeBytes { fullBuffer in
let adv = distance(from: startIndex, to: concreteRange.lowerBound)
let delta = distance(from: concreteRange.lowerBound, to: concreteRange.upperBound)
memcpy(ptr.baseAddress!, fullBuffer.baseAddress?.advanced(by: adv), delta)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ extension DispatchData : DataProtocol {
return index + bytes.count
}

public func withUnsafeBytes<ResultType>(_ body: (UnsafeRawBufferPointer) throws -> ResultType) rethrows -> ResultType {
public func withContiguousUnsafeBytes<ResultType>(_ body: (UnsafeRawBufferPointer) throws -> ResultType) rethrows -> ResultType {
return try body(UnsafeRawBufferPointer(bytes))
}
}
Expand Down