Swift Regret: Generic Parameters Aren't Members
Swift regret: generic parameters aren’t members. That is, when I declare `enum Optional<Wrapped>`, I should be able to refer to `Optional<Int>.Wrapped`.
— Jordan Rose (@UINT_MIN) October 13, 2021
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.