[swift-evolution] Revisiting 'T != Type' in where clause

Robert Bennett rltbennett at icloud.com
Thu Mar 16 22:32:11 CDT 2017


Agreed, I'm fine with a way of achieving this without T != Type. I suppose I should have made the subject "Fix Swift's type checker in this particular case".

I still have trouble figuring out *how* it can correctly handle ambiguity in protocol extensions but be unable to in a "true" (constructible) type extension. Does this warrant a bug report of some kind?

> On Mar 16, 2017, at 11:27 PM, Slava Pestov <spestov at apple.com> wrote:
> 
> Overload resolution has a lot of heuristics, but it’s not magic. It simply doesn’t know how to handle this case.
> 
> I’d be in favor of consolidating and simplifying the overload resolution rules, with the goal of disambiguating common cases that are currently ambiguous. We might even be able to do that without breaking too much user code, since a lot of the rules there were put in place to handle specific situations that came up in the standard library.
> 
> However adding more heuristics to handle specific examples is a -1 from me. :-)
> 
> Slava
> 
>> On Mar 16, 2017, at 7:38 PM, Jaden Geller via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> I would’ve expected overload resolution to pick the “more specific” one in this case without needing any additional constraints… 🤔
>> 
>>> On Mar 16, 2017, at 6:40 PM, Robert Bennett via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> Hello,
>>> 
>>> This discussion sort of fizzled out when the topic was first introduced. Joe Groff had asked the following:
>>> 
>>>> Do you have a concrete example where you need this? It'd be good to know whether the types are ambiguous due to type checker bugs, or whether there's a principle by which they could be naturally ordered.
>>> 
>>> There is an example of this ordering that I stumbled upon recently. Suppose I wish to extend `Array` with a `uniques()` function that returns an array containing the unique elements of `self`. For performance reasons, I would first write a method for arrays with Hashable elements, so that I could check for uniqueness in constant time per element.
>>> 
>>> extension Array where Element: Hashable {
>>> 	func uniques() -> [Element] {
>>> 		var seen: Set<Element> = []
>>> 		var uniq: [Element] = []
>>> 		
>>> 		for e in self {
>>> 			if !seen.contains(e) {
>>> 				seen.insert(e)
>>> 				uniq.append(e)
>>> 			}
>>> 		}
>>> 		
>>> 		return uniq
>>> 	}
>>> }
>>> 
>>> However I would still like to have a `uniques()` method for arrays whose elements are merely Equatable, and I'm willing to take the performance cost of O(n) lookup per element.
>>> 
>>> extension Array where Element: Equatable {
>>> 	func uniques() -> [Element] {
>>> 		var uniq: [Element] = []
>>> 		
>>> 		for e in self {
>>> 			if !uniq.contains(e) {
>>> 				uniq.append(e)
>>> 			}
>>> 		}
>>> 		
>>> 		return uniq
>>> 	}
>>> }
>>> 
>>> However, there is a problem, which is that elements that are Hashable are also Equatable, and so there is ambiguity when calling this method:
>>> 
>>> // error: ambiguous use of 'uniques()'
>>> print([1,2,3,1,2,4,5,1,2,3,4,5].uniques())
>>> 
>>> 
>>> If I could add `Element != Hashable` to the second extension, there would be no ambiguity.
>>> 
>>> FWIW replacing Array with Collection and Element with Iterator.Element fixes the error. The first extension (the one for Hashables) is called. I'm not sure why it is ambiguous in one case and not the other.
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 



More information about the swift-evolution mailing list