What is an associated type? Why can’t you write let x: MyPAT easily?
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
Selfrequirements also block existentials.EquatablehasSelfrequirements, which is whyany Equatableis 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 Equatablehard?==takesSelf, 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. →