Swift Regret: Generic Parameters Aren't Members

Part of the Swift Regrets series.

Generic parameters should behave like members. That is, when I declare enum Optional<Wrapped>, I should be able to refer to Optional<Int>.Wrapped.

…Okay, why? Usually because someone else has made their associated type Optional<ReallyObscureType<…>>, and it would be nice to say Foo.Context.Wrapped. (Sorry, this isn’t a great example….)

The thing is, there’s a lot of the compiler trying to fill this gap. Within a generic type, or even an extension thereof, unqualified (non-member) lookup will find generic parameters. When conforming to a protocol, they satisfy associated types (which makes a typealias that matches the generic parameter, by the way). But…the compiler doesn’t stop you from manually making a typealias with the same name. And things get weird if you do that.

Slava Pestov came up with a better reason: a type can end up with a member typealias that has the same name as a generic parameter, but a different type!

protocol P {
  associatedtype Element
  func get() -> Element
}

struct S<Element> : P {
  func get() -> Set<Element> {}
}

// S<Int>.Element == Set<Int>, not Int!

So the compiler would be simpler (and diagnostics might be better) if there was just a typealias member for any generic parameter of a type.