Search code examples
swiftgenericsstandard-library

Use of typealias syntax within protocols in the Swift standard library


In the Swift programming guide from Apple, it is described how to use the typealias keyword within protocols (from the section on Generics)

protocol Container {
  typealias ItemType
  mutating func append(item: ItemType)
  var count: Int { get }
  subscript(i: Int) -> ItemType { get }
}

which is then implemented:

struct IntStack: Container {
  typealias ItemType = Int // can sometimes be left out and inferred by the compiler
  mutating func append(item: Int) {
    self.push(item)
  }

// redacted
}

However, a significantly different use case is found in the Swift standard lib, e.g

public protocol ForwardIndexType : _Incrementable {

typealias Distance : _SignedIntegerType = Int

// redacted

}

or

public protocol CollectionType : Indexable, SequenceType {

typealias Generator : GeneratorType = IndexingGenerator<Self>
public func generate() -> Self.Generator

// redacted

}

together with:

extension CollectionType where Generator == IndexingGenerator<Self> {
  public func generate() -> IndexingGenerator<Self>
}

What does this syntax represent? It appears that the typealias is both declared, restricted (e.g. to GeneratorType) and assigned, all at once? What does this mean and why is it so? I expected to see assignment (=) only in implementing client code.

My understanding of typealias is that it represents a type, that is 'filled in' by the implementing code (as per generics) yet here it seems to implement a type for the typealias in the declaration, even though this is also done in the extension (where I would expect it).


Solution

  • Take a look at this answer. Use of a colon shows inheritance, use of an equals sign shows assignment.

    In my understanding this means the following:

    typealias X // defines associated type X for subclasses to override
    typealias X: Y // defines associated type X and requires that it conform to Y
    typealias X = Z // defines associated type X with a default of type Z
    typealias X: Y = Z // defines associated type X with a default of type Z and requires that any overrides conform to Y
    

    My interpretation seems to be supported by this article on Swift generics:

    An associated type is declared by a protocol using the typealias keyword. It normally set by an item that conforms to that protocol, although you can supply a default. Like type parameters, an associated type can be used as a token when building generic type rules.

    The use of the keyword typealias can be misleading for defining associated types and may be replaced by associatedtype in the future.