Hello dear Swift community, I waited with this pitch until the forum finally went live. Last year there were some topic regarding protocol nesting where this idea was born from.
Mainly this idea is meant to disambigute similar named types, but there are also other areas where this aligned behavior would come to a benifit.
Here a few snippets where I see this behavior as useful.
// Future direction:
class Generic<Element> {
protocol P {
// `Element` is not captured by P, but could allow the
// default to be generic type parameter, therefore the
// default for `Generic<Int>.P.Element` would be `Int`.
associatedtype Element = Generic.Element
}
// In case of value types the constraint should be
// `== Generic.Element`. This is a perfect case for
// disambiguation between associated type `Element`
// and the other generic paramter type `Element`.
typealias CapturedP = P where Element == Self.Element
var p: CapturedP
}
// Constraint that forces a nested generic type to have the same
// generic type parameter as the outer generic type, but still
// allowing both the be named the same.
struct FirstDimension<Element> {
// In Swift 4 inner `Element` is distinct from the outer `Element`.
struct SecondDimension<Element> where Element == FirstDimension.Element {
...
}
}
// Preventing generic type parameter shadowing like the following one:
struct Generic<Element> {
typealias Element = Int
var element: Element
}
// error: cannot convert value of type 'String'
// to expected argument type 'Generic.Element' (aka 'Int')
Generic<String>(element: "Swift 5")
// Allowing new generic algorithms similar to associated types
// directly on generic types by allowing ignoring some generic
// paramters.
struct Generic<A, B> {
var a: A
var b: B
}
func test<T>(_ t: T) where T : Generic, T.A == Int {
print(t.a * 10)
}
test(Generic<Int, Int>(a: 1, b: 2))
test(Generic<Int, String>(a: 3, b: "String"))
I'm sure there are other cases where this behavior can be beneficial. I fully understand that this alignment would probably be a breaking change and I can name a scenario that comes to my mind:
class SuperClass<Element> {}
class SubClass<Element> : SuperClass<Int> {}
In this case SubClass.Element == SuperClass.Element (or Self.Element) == Int
, at least I would assume that behavior.
Anyways, I'd like to see your feedback on this idea.