> 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
