Consider this example:
protocol P {
associatedtype T
func f() // *
}
extension P {
func f() { print("T is unknown") }
}
extension P where T == Int {
func f() { print("T is Int") }
}
struct X<T> : P {
func f() { print("this one is actually best") }
}
struct Y<U> where U: P, U.T == Int {
typealias T = U.T
var a: U
func g() { a.f() }
}
let x = X<Int>()
x.f() // "this one is actually best"
let y = Y(a: X<Int>())
y.g() // "this one is actually best"
I can't think of any other choice for 'a.f()' that would preserve this
behavior, which means we're doing the best thing: prefer dynamic dispatch over
static dispatch when operating on a generic value. (Or at least the "least bad"
thing.) And of course this reasoning has to be local; Y.g can't look and say
"oh, I know nothing else conforms to P, and X {does, doesn't} have a custom
implementation, so I should pick the constrained extension instead".
The real answer might be "we should have had a different syntax for default
implementations vs. mixin operations", but that's a much bigger can of worms.
Jordan
> On Dec 8, 2017, at 13:07, Jens Persson via swift-users
> <[email protected]> wrote:
>
> Thanks Slava and Greg,
>
> (
> I'm aware that it prints "T is Int" from both calls if I remove func f() from
> P itself, that's why I wrote "... unless * is commented out." in the comment
> of the last line
> Note that the "U.T == Int"-part of
> struct Y<U> where U: P, U.T == Int {
> is key here. If it had been only
> struct Y<U> where U: P {
> then I hadn't been surprised that it printed "T is unknown".
> )
>
> Filed https://bugs.swift.org/browse/SR-6564
> <https://bugs.swift.org/browse/SR-6564> since I think it is just strange that
> the compiler should not use its knowledge of U.T == Int when choosing between
> the two f()-implementations.
> I think I will be a little disappointed if the solution is to deem it an
> ambiguity
> : )
>
> /Jens
>
>
>
> On Fri, Dec 8, 2017 at 9:19 PM, Greg Parker <[email protected]
> <mailto:[email protected]>> wrote:
> Evidence in favor of Slava's analysis: if you remove `func f()` from P
> itself, leaving it in the extensions only, then you get "T is Int" from both
> calls.
>
>
> > On Dec 8, 2017, at 12:12 PM, Slava Pestov via swift-users
> > <[email protected] <mailto:[email protected]>> wrote:
> >
> > Hi Jens,
> >
> > I think the problem is that overload ranking always prefers a protocol
> > requirement to a protocol extension member, because usually you want the
> > dynamic dispatch through the requirement instead of calling the default
> > implementation. But it appears that this heuristic does not take into
> > account the fact that the protocol extension member could be more
> > constrained than the requirement.
> >
> > Please file a bug, but it is unclear what the desired behavior actually is
> > here. Perhaps it should just diagnose an ambiguity.
> >
> > Slava
> >
> >> On Dec 8, 2017, at 6:25 AM, Jens Persson via swift-users
> >> <[email protected] <mailto:[email protected]>> wrote:
> >>
> >> Hi all!
> >>
> >> Can someone please explain the rationale behind the last line printing
> >> "T is unknown"
> >> rather than (what I would expect):
> >> "T is Int"
> >> in the following program?
> >>
> >>
> >> protocol P {
> >> associatedtype T
> >> func f() // *
> >> }
> >> extension P {
> >> func f() { print("T is unknown") }
> >> }
> >> extension P where T == Int {
> >> func f() { print("T is Int") }
> >> }
> >>
> >> struct X<T> : P {}
> >>
> >> struct Y<U> where U: P, U.T == Int {
> >> // NOTE: The compiler/type-checker knows that U.T == Int here so ...
> >> typealias T = U.T
> >> var a: U
> >> func g() { a.f() } // ... how/why could this print anything but "T is
> >> Int"?
> >> }
> >>
> >> let x = X<Int>()
> >> x.f() // Prints "T is Int", no matter if * is commented out or not.
> >>
> >> let y = Y(a: X<Int>())
> >> y.g() // Prints "T is unknown" unless * is commented out. Why?
> >>
> >>
> >> IMHO this looks like the compiler simply ignores that struct Y<U> has the
> >> constraint U.T == Int.
> >> How else to explain this behavior?
> >> /Jens
> >>
> >> _______________________________________________
> >> swift-users mailing list
> >> [email protected] <mailto:[email protected]>
> >> https://lists.swift.org/mailman/listinfo/swift-users
> >> <https://lists.swift.org/mailman/listinfo/swift-users>
> >
> > _______________________________________________
> > swift-users mailing list
> > [email protected] <mailto:[email protected]>
> > https://lists.swift.org/mailman/listinfo/swift-users
> > <https://lists.swift.org/mailman/listinfo/swift-users>
>
>
> _______________________________________________
> swift-users mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-users
_______________________________________________
swift-users mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-users