Skip to content

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

Open
@Lukasa

Description

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions