Created
May 12, 2016 16:18
-
-
Save jckarter/e52836b888efd16fcf996d061750c37d to your computer and use it in GitHub Desktop.
Protocol extensions open existentials
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol HumanType {} | |
protocol HasName {} | |
func printHumanName<T: protocol<HumanType, HasName>>(x: T) {} | |
// It currently isn't possible to directly pass a protocol<> type value | |
// as a concrete value conforming to the protocol. However, a protocol | |
// extension method's Self type *is* a concrete type conforming to the | |
// extending protocol. By introducing extension methods we can "open" | |
// the protocol existential and use the opened Self type with generics. | |
// | |
// (Yes, this is a hacky workaround, and we should have first-class | |
// support for it in the language. Doug Gregor addresses this as | |
// a missing feature in the "Opening Existentials" section of his | |
// Generics Manifesto: | |
// https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md ) | |
extension HumanType where Self: HasName { | |
private func _printHumanName() { | |
printHumanName(x: self) | |
} | |
} | |
func tryToPrintUnknownData(unknownData: Any) { | |
if let unknownData = unknownData as? protocol<HumanType, HasName> { | |
// Compile Error: cannot invoke 'printHumanName' | |
// with an argument list of type '(protocol<HasName, HumanType>)' | |
/*printHumanName(unknownData)*/ | |
// However, we can use an extension method on the protocol value: | |
unknownData._printHumanName() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment