What is an associated type? Why can’t you write let x: MyPAT easily?

1.3.5 · L2 · Interview

Predict first

Does this compile?

protocol Container {
    associatedtype Item
    func first() -> Item
}

func firstNumber(_ c: any Container) -> Int {
    c.first()
}
  • Yes
  • No

Mental model. An associated type is a blank in a contract: “this type promises to supply some Element”. Until the blank is filled, it is not a type you can point at.

An associated type is a placeholder that the conforming type fills in, e.g. IteratorProtocol.Element. The protocol describes a family of types, not a single type.

So let x: Collection is incomplete — the compiler does not know what Element is, and therefore cannot lay out the value or resolve members that mention it. Before Swift 5.7 you either used generics (<T: Collection>) or wrote a type eraser (AnySequence). Since 5.7, a primary associated type lets you say any Collection<String>.

Through any Container the compiler no longer knows Item, so first() comes back type-erased (as Any), not Int. A generic some Container where Item == Int keeps it.

Common traps

  • “A PAT is just a generic protocol.” It is a protocol with a type-level parameter. The distinction matters for existentials and ABI.
  • Forgetting that Self requirements also block existentials. Equatable has Self requirements, which is why any Equatable is awkward.

They might follow up with

  • What is a type eraser? A concrete wrapper struct that hides the generic parameter — see Q21.
  • Why is any Equatable hard? == takes Self, and an existential cannot statically prove both sides are the same concrete type.

Related questions

  • 1.3.6 What is a primary associated type? Give an example.
  • 1.3.7 What is a type eraser (AnyHashable, AnyView, AnyCancellable)? When do you write one?
  • 1.4.1 Generics vs protocols as types: when do you write <T: P>(T) vs any P?

← Why might collection.map call the stdlib generic overload instead of…   What is a primary associated type? Give an example. →