> Am 09.06.2016 um 00:13 schrieb Matthew Johnson via swift-evolution 
> <[email protected]>:
> 
> 
>> On Jun 8, 2016, at 4:47 PM, Austin Zheng <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>> FWIW my opinion is that existentials either shouldn't be allowed to stand in 
>> for generic type parameters, or Dave's option #1 if they are.
>> 
>> The implied promise of a generic type parameter T right now is that T always 
>> stands for the same concrete type (modulo things like passing in a subclass 
>> where a class would do), and likewise for all of T's associated types (T.Foo 
>> is always the same type everywhere in the context where T is valid). This is 
>> what makes using anything with 'self' requirements in a generic context 
>> sound. Allowing existentials to satisfy T would violate that constraint. 
>> 
>> Relaxing these semantics would make it too easy to write code that traps at 
>> runtime "without the user having to reach" (to paraphrase Jordan from the 
>> "Swift philosophy" thread). Anyone who really really wants to write code 
>> that is 'compile-time unsound' in this way should have to explicitly type 
>> erase using concrete wrappers.
> 
> Yes, exactly.

Yup.

-Thorsten


> 
>> 
>> Best,
>> Austin
>> 
>> 
>> On Wed, Jun 8, 2016 at 2:37 PM, Austin Zheng <[email protected] 
>> <mailto:[email protected]>> wrote:
>> We might be talking past each other. I think Matthew is talking about using 
>> an existential outside the context of generic functions. For example, 
>> something like this should be trap-proof (as long as 'x' is immutable, which 
>> it is in this example):
>> 
>> func copySequenceIntoArray(x: Any<Sequence where .Iterator.Element == Int>) 
>> -> [Int] {
>>      var buffer : [Int] = []
>>         // Stupid implementation to make a point
>>      var iterator : x.Iterator = x.makeIterator()
>>      while true {
>>              let nextItem : Int? = iterator.next()
>>              if let nextItem = nextItem {
>>                      buffer.append(nextItem)
>>              } else {
>>                      return buffer
>>              }
>>      }
>> }
>> 
>> Even this would never trap as well:
>> 
>> func copySequenceIntoArray<T>(x: Any<Sequence where .Iterator.Element == T>) 
>> -> [T] {
>>      var buffer : [T] = []
>>      for item in x {
>>              buffer.append(item)
>>      }
>>      return buffer
>> }
>> 
>> Where we run into difficulty is something like this (forgive my abuse of the 
>> collections API; I don't remember all the new indexing APIs off the top of 
>> my head):
>> 
>> func doSomething<T : Collection where T.Element == Int>(x: T, y: T) {
>>      // Get indexes out of x and use them to index into y
>>      var idx = x.startIndex
>>      while (idx != x.endIndex || idx != y.endIndex) {
>>              print(x[idx])
>>              print(y[idx])
>>              idx = x.nextIndex(idx)
>>      }
>> }
>> let someSeq : Any<Collection where .Element == Int> = // ...
>> let anotherSeq : Any<Collection where .Element == Int> = // ...
>> // Trouble!
>> // someSeq and anotherSeq are the same existential type
>> // But the concrete index types within each of the existential variables may 
>> be different
>> doSomething(someSeq, anotherSeq)
>> 
>> It's this situation (using an existential type to fulfill a generic type 
>> parameter constrained to the same requirements that comprise that 
>> existential) that requires either of the two options that Dave presented, 
>> due to our lack of compile-time type information about the fulfilling type's 
>> associated types.
>> 
>> Best,
>> Austin
>> 
>> On Wed, Jun 8, 2016 at 2:33 PM, Matthew Johnson via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> 
>> Sent from my iPad
>> 
>> > On Jun 8, 2016, at 3:16 PM, Dave Abrahams via swift-evolution 
>> > <[email protected] <mailto:[email protected]>> wrote:
>> >
>> >
>> >> on Wed Jun 08 2016, Thorsten Seitz <[email protected] 
>> >> <mailto:[email protected]>> wrote:
>> >>
>> >> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>> >> to read up again what the reasons are for that behavior).
>> >
>> > Yes, but in the case of the issue we're discussing, the choices are:
>> >
>> > 1. Omit from the existential's API any protocol requirements that depend
>> >   on Self or associated types, in which case it *can't* conform to
>> >   itself because it doesn't fulfill the requirements.
>> 
>> They don't need to be omitted.  They are exposed in different ways depending 
>> on how the existential is constrained.  Austin's proposal was originally 
>> written to omit some members but it was modified based on feedback from Doug 
>> Gregor IIRC (Austin, is that right?).  Now it contains examples showing how 
>> these members are made available in a safe way.   Some members may still not 
>> be usable because you can't form an argument but IIRC the suggestion was 
>> that they be exposed anyway for consistency.
>> 
>> >
>> > 2. Erase type relationships and trap at runtime when they don't line up.
>> >
>> > Matthew has been arguing against #2, but you can't “fix the bug” without
>> > it.
>> >
>> >>
>> >> -Thorsten
>> >>
>> >>> Am 08.06.2016 um 21:43 schrieb Austin Zheng <[email protected] 
>> >>> <mailto:[email protected]>>:
>> >>>
>> >>> It's not possible, even with Swift's current implementation of
>> >>> existentials. A protocol type P isn't considered to conform to
>> >>> itself, thus the following is rejected:
>> >>>
>> >>> let a : MyProtocol = // ...
>> >>> func myFunc<T : MyProtocol>(x: T) {
>> >>>  // ....
>> >>> }
>> >>> myFunc(a) // "Cannot invoke 'myFunc' with an argument list of type 
>> >>> MyProtocol"
>> >>>
>> >>> Changing how this works is probably worth a proposal by itself.
>> >>>
>> >>> Austin
>> >>>
>> >>>
>> >>> On Wed, Jun 8, 2016 at 12:34 PM, Thorsten Seitz via swift-evolution
>> >>> <[email protected] <mailto:[email protected]>
>> >>> <mailto:[email protected] <mailto:[email protected]>>>
>> >>> wrote:
>> >>>
>> >>>> Am 08.06.2016 um 20:33 schrieb Dave Abrahams via swift-evolution
>> >>>> <[email protected] <mailto:[email protected]>
>> >>>> <mailto:[email protected] <mailto:[email protected]>>>:
>> >>>>
>> >>>>
>> >>>> on Tue Jun 07 2016, Matthew Johnson <matthew-AT-anandabits.com 
>> >>>> <http://matthew-at-anandabits.com/>> wrote:
>> >>>>
>> >>>>>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams
>> >>>>>> <[email protected] <mailto:[email protected]>
>> >>>>>> <mailto:[email protected] <mailto:[email protected]>>>
>> >>>>>> wrote:
>> >>>>>>
>> >>>>>>
>> >>>>>> on Tue Jun 07 2016, Matthew Johnson <matthew-AT-anandabits.com 
>> >>>>>> <http://matthew-at-anandabits.com/>
>> >>>>>> <http://matthew-at-anandabits.com/ <http://matthew-at-anandabits.com/>
>> >>>>>> <http://matthew-at-anandabits.com/ 
>> >>>>>> <http://matthew-at-anandabits.com/>>>> wrote:
>> >>>>>
>> >>>>>>>> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution
>> >>>>>>>> <[email protected] <mailto:[email protected]>
>> >>>>>>>> <mailto:[email protected] 
>> >>>>>>>> <mailto:[email protected]>>>
>> >>>>>>>> wrote:
>> >>>>>>>>
>> >>>>>>>>
>> >>>>>>>> on Tue Jun 07 2016, Matthew Johnson
>> >>>>>>>> <[email protected] <mailto:[email protected]>
>> >>>>>>>> <mailto:[email protected] 
>> >>>>>>>> <mailto:[email protected]>>>
>> >>>>>>>> wrote:
>> >>>>>>>
>> >>>>>>>>>> , but haven't realized
>> >>>>>>>>>> that if you step around the type relationships encoded in Self
>> >>>>>>>>>> requirements and associated types you end up with types that 
>> >>>>>>>>>> appear to
>> >>>>>>>>>> interoperate but in fact trap at runtime unless used in exactly 
>> >>>>>>>>>> the
>> >>>>>>>>>> right way.
>> >>>>>>>>>
>> >>>>>>>>> Trap at runtime?  How so?  Generalized existentials should still be
>> >>>>>>>>> type-safe.
>> >>>>>>>>
>> >>>>>>>> There are two choices when you erase static type relationships:
>> >>>>>>>>
>> >>>>>>>> 1. Acheive type-safety by trapping at runtime
>> >>>>>>>>
>> >>>>>>>> FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
>> >>>>>>>>
>> >>>>>>>> 2. Don't expose protocol requirements that involve these 
>> >>>>>>>> relationships,
>> >>>>>>>> which would prevent the code above from compiling and prevent
>> >>>>>>>> FloatingPoint from conforming to itself.
>> >>>>>>>>
>> >>>>>>>>> Or are you talking about the hypothetical types / behaviors people
>> >>>>>>>>> think they want when they don’t fully understand what is 
>> >>>>>>>>> happening...
>> >>>>>>>>
>> >>>>>>>> I don't know what you mean here.  I think generalized existentials 
>> >>>>>>>> will
>> >>>>>>>> be nice to have, but I think most people will want them to do 
>> >>>>>>>> something
>> >>>>>>>> they can't possibly do.
>> >>>>>>>
>> >>>>>>> Exactly.  What I meant is that people think they want that expression
>> >>>>>>> to compile because they don’t understand that the only thing it can 
>> >>>>>>> do
>> >>>>>>> is trap.  I said “hypothetical” because producing a compile time 
>> >>>>>>> error
>> >>>>>>> rather than a runtime trap is the only sane thing to do.  Your 
>> >>>>>>> comment
>> >>>>>>> surprised me because I can’t imagine we would move forward in Swift
>> >>>>>>> with the approach of trapping.
>> >>>>>>
>> >>>>>> I would very much like to be able to create instances of “Collection
>> >>>>>> where Element == Int” so we can throw away the wrappers in the stdlib.
>> >>>>>> That will require some type mismatches to be caught at runtime via
>> >>>>>> trapping.
>> >>>>>
>> >>>>> For invalid index because the existential accepts a type erased index?
>> >>>>
>> >>>> Exactly.
>> >>>>
>> >>>>> How do you decide where to draw the line here?  It feels like a very
>> >>>>> slippery slope for a language where safety is a stated priority to
>> >>>>> start adopting a strategy of runtime trapping for something as
>> >>>>> fundamental as how you expose members on an existential.
>> >>>>
>> >>>> If you don't do this, the alternative is that “Collection where Element
>> >>>> == Int” does not conform to Collection.  That's weird and not very
>> >>>> useful.  You could expose all the methods that were on protocol
>> >>>> extensions of Collection on this existential, unless they used
>> >>>> associated types other than the element type.  But you couldn't pass the
>> >>>> existential to a generic function like
>> >>>>
>> >>>>  func scrambled<C: Collection>(_ c: C) -> [C.Element]
>> >>>
>> >>> I don’t understand. Why couldn’t an existential be passed to that 
>> >>> function?
>> >>>
>> >>> -Thorsten
>> >>>
>> >>>
>> >>>
>> >>>>
>> >>>>> IMO you should *have* to introduce unsafe behavior like that manually.
>> >>>>
>> >>>> Collection where Element == Int & Index == *
>> >>>>
>> >>>> ?
>> >>>>
>> >>>>> Collection indices are already something that isn’t fully statically
>> >>>>> safe so I understand why you might want to allow this.
>> >>>>
>> >>>> By the same measure, so are Ints :-)
>> >>>>
>> >>>> The fact that a type's methods have preconditions does *not* make it
>> >>>> “statically unsafe.”
>> >>>>
>> >>>>> But I don’t think having the language's existentials do this
>> >>>>> automatically is the right approach.  Maybe there is another approach
>> >>>>> that could be used in targeted use cases where the less safe behavior
>> >>>>> makes sense and is carefully designed.
>> >>>>
>> >>>> Whether it makes sense or not really depends on the use-cases.  There's
>> >>>> little point in generalizing existentials if the result isn't very 
>> >>>> useful.
>> >>>> The way to find out is to take a look at the examples we currently have
>> >>>> of protocols with associated types or Self requirements and consider
>> >>>> what you'd be able to do with their existentials if type relationships
>> >>>> couldn't be erased.
>> >>>>
>> >>>> We have known use-cases, currently emulated in the standard library, for
>> >>>> existentials with erased type relationships.  *If* these represent the
>> >>>> predominant use cases for something like generalized existentials, it
>> >>>> seems to me that the language feature should support that.  Note: I have
>> >>>> not seen anyone build an emulation of the other kind of generalized
>> >>>> existential.  My theory: there's a good reason for that :-).
>> >>>>
>> >>>> --
>> >>>> Dave
>> >>>> _______________________________________________
>> >>>> swift-evolution mailing list
>> >>>> [email protected] <mailto:[email protected]>
>> >>>> <mailto:[email protected] <mailto:[email protected]>>
>> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution 
>> >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>>
>> >>>
>> >>> _______________________________________________
>> >>> swift-evolution mailing list
>> >>> [email protected] <mailto:[email protected]>
>> >>> <mailto:[email protected] <mailto:[email protected]>>
>> >>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> >>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> >>> <https://lists.swift.org/mailman/listinfo/swift-evolution 
>> >>> <https://lists.swift.org/mailman/listinfo/swift-evolution>>
>> >>
>> >> _______________________________________________
>> >> swift-evolution mailing list
>> >> [email protected] <mailto:[email protected]>
>> >> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> >> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> >
>> > --
>> > Dave
>> >
>> > _______________________________________________
>> > swift-evolution mailing list
>> > [email protected] <mailto:[email protected]>
>> > https://lists.swift.org/mailman/listinfo/swift-evolution 
>> > <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> 
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to