Skip to content

Instantly share code, notes, and snippets.

@jckarter
Created May 12, 2016 16:18
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jckarter/e52836b888efd16fcf996d061750c37d to your computer and use it in GitHub Desktop.
Save jckarter/e52836b888efd16fcf996d061750c37d to your computer and use it in GitHub Desktop.
Protocol extensions open existentials
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