From cc5990232bdf589579d5b497deab354a3042ec7d Mon Sep 17 00:00:00 2001 From: David Grove Date: Wed, 4 Jan 2017 13:07:10 -0500 Subject: [PATCH] SR-3477: replace unsafeBitCast by withoutActuallyEscaping Now that withoutActuallyEscaping is implemented, use it instead of unsafeBitCast to allow passing a closure capturing a non-escaping block down to the C implementation of dispatch_data_apply (which does not actually escape its block argument). --- src/swift/Data.swift | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/swift/Data.swift b/src/swift/Data.swift index fc0bc0944..d51205ce7 100644 --- a/src/swift/Data.swift +++ b/src/swift/Data.swift @@ -91,14 +91,18 @@ public struct DispatchData : RandomAccessCollection { public func enumerateBytes( block: (_ buffer: UnsafeBufferPointer, _ byteIndex: Int, _ stop: inout Bool) -> Void) { - // FIXME: When SR-2313 (withoutActuallyEscaping) is implemented, use it to replace unsafeBitCast - let nonEscapingBlock = unsafeBitCast(block, to: _enumerateBytesBlock.self) - _ = CDispatch.dispatch_data_apply(__wrapped.__wrapped) { (_, offset: Int, ptr: UnsafeRawPointer, size: Int) in - let bytePtr = ptr.bindMemory(to: UInt8.self, capacity: size) - let bp = UnsafeBufferPointer(start: bytePtr, count: size) - var stop = false - nonEscapingBlock(bp, offset, &stop) - return !stop + // we know that capturing block in the closure being created/passed to dispatch_data_apply + // does not cause block to escape because dispatch_data_apply does not allow its + // block argument to escape. Therefore, the usage of withoutActuallyEscaping to + // bypass the Swift type system is safe. + withoutActuallyEscaping(block) { escapableBlock in + _ = CDispatch.dispatch_data_apply(__wrapped.__wrapped) { (_, offset: Int, ptr: UnsafeRawPointer, size: Int) in + let bytePtr = ptr.bindMemory(to: UInt8.self, capacity: size) + let bp = UnsafeBufferPointer(start: bytePtr, count: size) + var stop = false + escapableBlock(bp, offset, &stop) + return !stop + } } } @@ -273,8 +277,6 @@ public struct DispatchDataIterator : IteratorProtocol, Sequence { internal var _position: DispatchData.Index } -typealias _enumerateBytesBlock = (_ buffer: UnsafeBufferPointer, _ byteIndex: Int, _ stop: inout Bool) -> Void - @_silgen_name("_swift_dispatch_data_empty") internal func _swift_dispatch_data_empty() -> dispatch_data_t