> On Jun 8, 2016, at 4:47 PM, Austin Zheng <[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.

> 
> 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> 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/>>>> 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

Reply via email to