Hi,
I'm having an issue with a generic function which accepts a collection of tuples:
struct Foo {
public mutating func append<CollectionType, StringType>(
contentsOf keyValuePairs: CollectionType
) where CollectionType: Collection, CollectionType.Element == (StringType, StringType), StringType: StringProtocol {
// ...
}
}
This function only appears to work if the tuples are unlabelled. If, for instance, I wanted to append the contents of a Dictionary
(whose Element
is the labelled tuple (key: Key, value: Value)
), it won't compile:
var x = Foo()
x.append(contentsOf: ["bar": "bar", "baz": "baz"])
// Error: instance method 'append(contentsOf:)' requires the types '(key: String, value: String)' and '(StringType, StringType)' be equivalent
However, if I take the tuple out of the generic constraints, things appear to work as expected:
struct Foo {
public mutating func append_single<StringType>(
_ keyValuePair: (StringType, StringType)
) where StringType: StringProtocol {
}
}
var x = Foo()
x.append_single(["bar": "bar", "baz": "baz"].first!) // Works.
Unfortunately, this workaround isn't really acceptable - I really do need to be able to append an entire Collection
of tuples, meaning I need the tuple to be expressed in the generic constraints.
The only solution I can think of is just to duplicate the function - one version with tuple labels, and another without, which lazy-map to call a common implementation. It's fine (as long as I can predict the precise labels users will use), but it's a bit clunky.
What I'd like to know is: is this a bug (i.e. unintentional)? And if not, are there language enhancements that could be made so that the presence of a tuple label does not prohibit users from calling the function which does not use labels?