If I'm understanding this revision correctly, this proposal derives the base type for the implicit member expression entirely from the type of Self
in the same-type constraint, and not at all from the particular member—is that correct?
I.e., would this now be allowed?
protocol P {}
struct S: P {}
struct R: P {}
extension P where Self == S {
static var r: R { R() }
}
extension R {
var s: S { S() }
}
test<T: P>(_: T) {}
test(.r.s) // Ok
Also, does this proposal use the semantics mentioned in the previous review thread?
?
I.e., what gets printed in this example?
protocol P {}
struct S: P {}
extension P where Self == S {
static var s: S {
print("s via P")
return S()
}
}
extension S {
static var s: S {
print("s via S")
return S()
}
}
test<T: P>(_: T) {}
test(.s) // ?
IMO this revision results in more explainable behavior, and is more inline with existing inference rules in similar positions (such as the examples @Joe_Groff posted here).
If the example above prints "s via P" then I'm fully on board with this revision.
If the example above would print "s via S" then I remain concerned about the ability of a declaration guide type-checking that does not appear in the final expression. The author of P
would not, for instance, be able to remove P.s
by deprecating the declaration for a time and then deleting it, because they could not be sure that all clients depending on the declaration would actually see the deprecation warning before removal.