- Proposal: SE-0092
- Authors: David Hart, Doug Gregor
- Review Manager: Chris Lattner
- Status: Implemented (Swift 3.0)
- Decision Notes: Rationale
- Bug: SR-1539
This proposal is from the Generics Manifesto and brings the typealias
keyword back into protocols for type aliasing.
In Swift versions prior to 2.2, the typealias
keyword was used outside of protocols to declare type aliases and in protocols to declare associated types. Since SE-0011 and Swift 2.2, associated type now use the associatedtype
keyword and typealias
is available for implementing true associated type aliases.
The solution allows the creation of associated type aliases. Here is an example from the standard library:
protocol Sequence {
associatedtype Iterator : IteratorProtocol
typealias Element = Iterator.Element
}
The example above shows how this simplifies referencing indirect associated types:
func sum<T: Sequence where T.Element == Int>(sequence: T) -> Int {
return sequence.reduce(0, combine: +)
}
Allowing typealias
in protocol extensions also allows extensions to use aliases to simplify code that the protocol did not originally propose:
extension Sequence {
typealias Element = Iterator.Element
func concat(other: Self) -> [Element] {
return Array<Element>(self) + Array<Element>(other)
}
}
The following grammar rules needs to be added:
protocol-member-declaration → protocol-typealias-declaration
protocol-typealias-declaration → typealias-declaration
This will initially have no impact on existing code, but will probably require improving the Fix-It that was created for migrating typealias
to associatedtype
in Swift 2.2.
But once typealias
starts being used inside protocols, especially in the Standard Library, name clashes might start cropping up between the type aliases and associated types. For example:
protocol Sequence {
typealias Element = Iterator.Element // once this is added
}
protocol MySequence: Sequence {
associatedtype Element // MySequence.Element is ambiguous
}
But there is no reason that those name clashes behave differently than current clashes between associated types:
protocol Foo {
associatedtype Inner: IntegerType
func foo(inner: Inner)
}
protocol Bar {
associatedtype Inner: FloatingPointType
var inner: Inner { get }
}
struct FooBarImpl: Foo, Bar { // error: Type ‘FooBarImpl’ does not conform to protocol ‘Bar'
func foo(inner: Int) {}
var inner: Float
}