Re: [swift-users] Swift's method dispatch

2017-12-08 Thread Jordan Rose via swift-users
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 : P {
func f() { print("this one is actually best") }
}

struct Y where U: P, U.T == Int {
typealias T = U.T
var a: U
func g() { a.f() }
}

let x = X()
x.f() // "this one is actually best"

let y = Y(a: X())
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 
>  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 where U: P, U.T == Int {
> is key here. If it had been only
>   struct Y 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  > 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 
> > > 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 
> >> > 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 : P {}
> >>
> >> struct Y 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()
> >> x.f() // Prints "T is Int", no matter if * is commented out or not.
> >>
> >> let y = Y(a: X())
> >> y.g() // Prints "T is unknown" unless * is commented out. Why?
> >>
> >>
> >> IMHO this looks like the compiler simply ignores that struct Y 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

Re: [swift-users] Swift's method dispatch

2017-12-08 Thread Greg Parker via swift-users
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 
>  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 
>>  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 : P {}
>> 
>> struct Y 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()
>> x.f() // Prints "T is Int", no matter if * is commented out or not.
>> 
>> let y = Y(a: X())
>> y.g() // Prints "T is unknown" unless * is commented out. Why?
>> 
>> 
>> IMHO this looks like the compiler simply ignores that struct Y 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


Re: [swift-users] Swift's method dispatch

2017-12-08 Thread Slava Pestov via swift-users
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 
>  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 : P {}
> 
> struct Y 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()
> x.f() // Prints "T is Int", no matter if * is commented out or not.
> 
> let y = Y(a: X())
> y.g() // Prints "T is unknown" unless * is commented out. Why?
> 
> 
> IMHO this looks like the compiler simply ignores that struct Y 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] Swift's method dispatch

2017-12-08 Thread Jens Persson via swift-users
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 : P {}

struct Y 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()
x.f() // Prints "T is Int", no matter if * is commented out or not.

let y = Y(a: X())
y.g() // Prints "T is unknown" unless * is commented out. Why?


IMHO this looks like the compiler simply ignores that struct Y 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


Re: [swift-users] Multiple Class Types in Protocol Composition

2017-12-08 Thread Mario Meili via swift-users
Hi Slava,

Thank you very much for the quick response. As you requested, I filed the bug 
under the following link: https://bugs.swift.org/browse/SR-6561

Best Regards
Mario

From:  on behalf of Slava Pestov 
Date: Thursday, 7 December 2017 at 22:27
To: Mario Meili 
Cc: "swift-users@swift.org" 
Subject: Re: [swift-users] Multiple Class Types in Protocol Composition

Hi Mario,

You’re right that this part of the proposal was not fully implemented. 
Computing the common ancestor of two superclasses is a little tricky here 
because it would force us to resolve the superclass type of a class when 
realizing a subclass existential. This would introduce circular dependencies. 
Either I missed something obvious or it would require some re-architecting of 
the type checker to make it work.

Either way, yes it’s a known limitation, but not one that is tracked by a JIRA 
presently, so please do file a bug!

Thanks,

Slava


On Dec 7, 2017, at 7:17 AM, Mario Meili via swift-users 
> wrote:

Hi everyone,

I noticed strange behaviour of the Swift 4.0.3 compiler regarding class and 
subtype existentials.

According to the proposal SE-0156 
(https://github.com/apple/swift-evolution/blob/master/proposals/0156-subclass-existentials.md),
 multiple class types in protocol compositions should be allowed, if:


  *   The class types are the same
  *   Or, one class type must be a subtype of the other.

However, when copying the exact code from the proposal into Xcode 9.2, the 
result is the following:



My conclusion here is that the compiler does not allow multiple class types in 
one protocol composition.

My question is:
Is this behaviour intended or should I open a bug report?

Thank you very much

BR
Mario
___
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