Ah, I guess that's where the qualification syntax would come in. You'd have to use something like Outer.Self (and I don't know if that currently exists).
The “concrete Self” is not a generic parameter and the prohibition is specifically on multiple generic parameters with the same name.
That's true. I think it feels wrong to me because concrete Self still feels like a "keyword" that has special meaning even in non-generic contexts, especially since the construct above makes concrete Self inaccessible. Granted, concrete Self isn't strictly needed in that case because there's another way to spell it: the return type of f() can be made explicitly Inner.
It looks like the same problem persists if Inner is a class instead though, in which case f() is now returning dynamic Self and there is no alternative way to spell that (that I know of?). In that case, I guess users just shouldn't do that.
Sometimes you want the type info; sometimes you don't. When this feature gets taken on, it won't make sense to do it without extending the same capabilities to protocols and to concrete types.
protocol OptionalProtocol { associatedtype Nil: Error }
extension Optional: OptionalProtocol { struct Nil: Error { } }
func f<O: OptionalProtocol>(optional: O) throws(O.Nil) { } // Compiles
func f(optional: some Optional) throws((any Optional).Nil) { } // Doesn't, for multiple reasons.
It seems to me that "existential-style syntax" would do the job. There's broken stuff with similarly-spelled opaque types to deal with before tackling that though:
func f(optional: some OptionalProtocol) {
type(of: optional).Nil // ✅ '(some OptionalProtocol).Nil.Type'
// crashes the compiler.
let explicit: (some OptionalProtocol).Nil.Type = Int?.Nil.self
var computed: (some OptionalProtocol).Nil.Type {
Int?.Nil.self // Underlying type for opaque result type '((some OptionalProtocol).Nil).Type' could not be inferred from return expression
}
(any OptionalProtocol).Nil.self // Cannot access associated type 'Nil' from 'any OptionalProtocol'; use a concrete type or generic parameter base instead
(any Optional).Nil.self // 'any' has no effect on concrete type 'Optional'
}
The second diagnostic is correct, and the first one should produce the same diagnostic instead of crashing.