swiftlang / swiftlang/swift-corelibs-libdispatch
[SR-7868] Data and DispatchData have subtly different signatures for enumerateBytes
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 2.6k
- Forks
- 496
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 3
Description
| Previous ID | SR-7868 |
| Radar | rdar://problem/40775762 |
| Original Reporter | @Lukasa |
| Type | Bug |
Environment
Swift 4.2 beta
Additional Detail from JIRA
| Votes | 0 |
| Component/s | Foundation, libdispatch |
| Labels | Bug |
| Assignee | None |
| Priority | Medium |
md5: 7f82935997669109761a47ee765077b8
Issue Description:
While attempting to write a protocol for both Data and DispatchData that covers their shared `enumerateBytes` method, I discovered that it is not really possible to do that. Consider the following example program:
import struct Foundation.Data
import struct Dispatch.DispatchData
protocol ByteEnumerator: Collection {
func enumerateBytes(block: (UnsafeBufferPointer<UInt8>, Self.Index, inout Bool) -> Void)
}
extension Data: ByteEnumerator { }
extension DispatchData: ByteEnumerator { }
This does not compile, because Data has no label on its block:
test.swift:8:1: error: method 'enumerateBytes' has different argument labels from those required by protocol 'ByteEnumerator' ('enumerateBytes(block:)')
extension Data: ByteEnumerator { }
^
Foundation.Data:40:17: note: 'enumerateBytes' declared here
public func enumerateBytes(_ block: (UnsafeBufferPointer<UInt8>, Data.Index, inout Bool) -> Void)
^
test.swift:5:10: note: requirement 'enumerateBytes(block:)' declared here
func enumerateBytes(block: (UnsafeBufferPointer<UInt8>, Self.Index, inout Bool) -> Void)
If you try to suppress the label by changing the protocol method from func enumerateBytes(block: (UnsafeBufferPointer<UInt8>, Self.Index, inout Bool) -> Void) to func enumerateBytes(_ block: (UnsafeBufferPointer<UInt8>, Self.Index, inout Bool) -> Void), this will again fail to compile, this time because of DispatchData:
test.swift:9:1: error: method 'enumerateBytes(block:)' has different argument labels from those required by protocol 'ByteEnumerator' ('enumerateBytes')
extension DispatchData: ByteEnumerator { }
^
Dispatch.DispatchData:19:17: note: 'enumerateBytes(block:)' declared here
public func enumerateBytes(block: (UnsafeBufferPointer<UInt8>, Int, inout Bool) -> Void)
^
test.swift:5:10: note: requirement 'enumerateBytes' declared here
func enumerateBytes(_ block: (UnsafeBufferPointer<UInt8>, Self.Index, inout Bool) -> Void)
Given that these two data types can be bridged on Darwin, but not Linux, this inconsistency should probably be remedied.
(As a post-script, a tempting approach to bridge over this would be for my protocol to provide a default implementation for one case in terms of the other. However, because of the tail-closure syntax, doing this would cause an enormous number of compile errors.)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the Data and DispatchData enumerateBytes declarations referenced in the compiler diagnostics, then compare their argument labels and closure signatures. Reproduce the protocol examples with the stated Swift 4.2 behavior and determine a consistent API shape; the issue is done when both types can satisfy the same protocol without label-related compilation errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100