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 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 <gpar...@apple.com> 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 < > swift-users@swift.org> 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 < > swift-users@swift.org> 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 > >> swift-users@swift.org > >> https://lists.swift.org/mailman/listinfo/swift-users > > > > _______________________________________________ > > swift-users mailing list > > swift-users@swift.org > > https://lists.swift.org/mailman/listinfo/swift-users > >
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users