Skip to content
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

[SR-7868] Data and DispatchData have subtly different signatures for enumerateBytes #652

Open
Lukasa opened this issue Jun 4, 2018 · 2 comments

Comments

@Lukasa
Copy link
Contributor

Lukasa commented Jun 4, 2018

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.)

@Lukasa
Copy link
Contributor Author

Lukasa commented Jun 4, 2018

@swift-ci create

@Lukasa
Copy link
Contributor Author

Lukasa commented Jun 4, 2018

I should note that this affects both Darwin and Linux identically.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant