> On Jun 8, 2016, at 11:52 PM, Russ Bishop <[email protected]> wrote: > >> >> On Jun 8, 2016, at 3:18 PM, Dave Abrahams via swift-evolution >> <[email protected] <mailto:[email protected]>> wrote: >> >> Exactly. But much simpler cases will also either have to trap at >> runtime or be prohibited outright: >> >> func subscript_<C: Collection>(c: C, i: C.Index) -> C.Collection.Element { >> return c[i] >> } >> >> typealias IntCollection = Any<Collection where Element == Int> >> let c1: IntCollection = ... >> let c2: IntCollection = c1[3..<10] >> let c3: IntCollection = ... >> let c4: IntCollection = c1.reversed() >> >> // Note: the underlying index types are the same, and are supposed to >> // interoperate. What do you do (work/trap/nocompile)? >> _ = subscript_(c1, c2.startIndex) >> >> // The underlying index types happen to be the same, and are not >> // supposed to interoperate. What do you do (silently >> “work”/trap/nocompile)? >> _ = subscript_(c1, c3.startIndex) >> >> // The underlying index types are different. What do you do >> (trap/nocompile)? >> _ = subscript_(c1, c4.startIndex) >> >> -- >> Dave > > Is it sufficient to say that unconstrained associated types cannot satisfy > generic constraints so subscript_ can’t be called with startIndex? > Presumably if you said Any<Collection where Element == Int, Index == Int> you > could then call subscript_.
Presumably, if a type was of existential type but all its associated types were constrained to concrete types and none contain Self requirements, you should be able to use it to satisfy a generic parameter. (Self requirements are still a problem. `Equatable` has no associated types, but you'd still run into problems using that existential in a generic context.) Practically speaking, this wouldn't be too useful for most complex protocols. Swift 3's `Collection` defines at least `SubSequence`, `Indices`, `Index` (I think), and `Iterator`, all of which would have to be bound to meet this requirement. Then you get into recursive associated type constraints... > > Not being a compiler expert another thought occurs to me: Can the type of an > existential/unconstrained associated type be an unique anonymous type in the > local scope? In this case c1.startIndex is of type a’; it cannot be stored in > a global, passed to another function, etc. It is only usable in the current > scope for interacting with c1. c2.startIndex would be of type b’, etc. This > is similar to how anonymous types work in C#. The issues with func<X>(a: X, > b: X) could in theory be solved the same way: require opening the existential > in the local scope and validating that the actual types are identical before > you can call func. Joe Groff thinks it's possible. I wrote something up along those lines here: https://github.com/austinzheng/swift-evolution/blob/az-existentials/proposals/XXXX-enhanced-existentials.md#associated-types-and-member-exposure <https://github.com/austinzheng/swift-evolution/blob/az-existentials/proposals/XXXX-enhanced-existentials.md#associated-types-and-member-exposure> > > In that sense you could say the types are really: > > let c1: a’<IntCollection> > let c2: b’<IntCollection> > let c3: c’<IntCollection> > let c4: d’<IntCollection> > > // accepts responsibility for a and b being different concrete types at > runtime > func doIt(a: IntCollection, b: IntCollection) { } > > // caller must prove a & b are same concrete type > func makeIt<C: Collection>(a: C, b: C) { } > > > They are completely separate types until proven otherwise and you can’t go > passing them around unless the callee accepts responsibility for the dynamism > or you prove exactly which type you’re talking about. > > (I freely admit this may be nonsensical or impossible to implement reasonably > in the compiler) > > > Russ
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
