Sent from my iPad

> On Dec 10, 2017, at 4:30 PM, Jens Persson <j...@bitcycle.com> wrote:
> 
> Thank you Matthew, I will try to digest and incorporate your explanation.
> 
> I'm using a recent snapshot where
> struct X<T> : P {
>     func f() { print("this one is actually best") }
> }
> compiles fine without requiring that type alias.

Oh, that’s awesome!  I didn’t know this works in the latest snapshots.  I’m 
really happy to know this works now.

> 
> 
> /Jens
> 
> 
>> On Sun, Dec 10, 2017 at 10:52 PM, Matthew Johnson <matt...@anandabits.com> 
>> wrote:
>> 
>> 
>> Sent from my iPad
>> 
>>> On Dec 10, 2017, at 3:41 PM, Jens Persson via swift-users 
>>> <swift-users@swift.org> wrote:
>>> 
>>> I'm trying to get my head around the current behavior, but its very hard to 
>>> understand and remember, and judging by the comments here and on my bug 
>>> report (SR-6564), so does even people in the core team. It would be nice if 
>>> someone could present a complete set of rules (all the ones I've seen are 
>>> far to simplified and does not cover all cases).
>>> Here's another example to consider:
>>> 
>>> 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 {
>> 
>> FWIW, this does not compile.  You need to provide a typealias for T which 
>> you can’t do when the generic parameter is named T.
>> 
>>>     func f() { print("this one is actually best") }
>>> }
>>> extension X where T == Int {
>>>     func f() { print("this one is actually better than 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() // What will this print?
>> 
>> This prints “this one is actually better than best.” because the method is 
>> invoked on a concrete type.  Overload resolution is used to identify the 
>> most specific implementation which in this case is the method in the 
>> concrete extension on X.
>> 
>>> 
>>> let y = Y(a: X<Int>())
>>> y.g() // What will this print?
>> 
>> This prints ”this one is actually best”.  This is because the method is 
>> called in a generic context and is a protocol requirement.  This means it is 
>> dispatched through the protocol witness table.  The methods in the 
>> extensions on P are default implementations which are disregarded because X 
>> provides its own implementation.  The overload in the extension on X is not 
>> visible at all in a generic context because it does not participate in X’s 
>> conformance to P.
>> 
>>> 
>>> If anyone knows for sure what this program will print (without having to 
>>> run it), please enlighten me!
>> 
>> I hope the above helps.  If you have further questions please ask!
>> 
>>> 
>>> /Jens
>>> 
>>> 
>>>> On Sat, Dec 9, 2017 at 1:54 AM, Jordan Rose <jordan_r...@apple.com> wrote:
>>>> 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 
>>>>> <swift-users@swift.org> 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 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
>>>> 
>>> 
>>> _______________________________________________
>>> 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

Reply via email to