[swift-evolution] [swift-evolution-announce] [Review] SE-0108: Remove associated type inference
brent at architechies.com
Wed Jun 29 18:38:38 CDT 2016
> * What is your evaluation of the proposal?
I don't think the time is right.
I've been reading the code for Sequence, Collection, and the various protocols that they use (I actually went to bed with an almost finished email for the discussion thread), and I think this is going to be a big problem there. From what I can see, there are two places where they lean heavily on inference for basic usability:
1. `Sequence.SubSequence` has no default type, but it is inferred to be `AnySequence<Iterator.Element>` in the absence of an alternative, because the standard library provides an extension full of `AnySequence<Iterator.Element>`-returning implementations. Honestly, I'm not sure why it doesn't have a default—some very basic testing in the REPL didn't seem to show any circularity problems—so my guess is that this one could be resolved.
2. `Collection._Element` (actually `IndexableBase._Element`) is a *hidden* associated type which uses inference to break a nasty loop between `Collection` and `IndexingIterator`. (`IndexingIterator` wants to use the `Iterator.Element` of the collection it's used with, but if that `Iterator` is itself `IndexingIterator`, that would be a circular definition. Instead, it uses the collection's `_Element`, which is inferred to be the return type of the index subscript.) Without inference, we would have two options here, neither of them great:
a. Make `Collection.Element` a publicly visible associated type. Because we don't have `where` clauses for associated types yet, that would make it very easy to create a Collection whose `Element` and `Iterator.Element` did not match. (If we *do* make it a non-hidden associated type, I would suggest we add same-named generic parameters as another way to implicitly fulfill an associated type requirement; that would handle many collections automatically.)
b. Make the element type a second generic parameter to `IndexingIterator`. This would effectively prevent us from offering a default `Iterator` on `Collection`s.
Additionally, I believe the other un-defaulted associated types we'd like to infer if we can—`Collection.Index`, `Sequence.Iterator`, and `IteratorProtocol.Element`—could all be handled by simple "caveman inference" heuristics, rather than a full type inference pass. All three of these are used in either the types of un-defaulted properties (which cannot ever be overloaded) or the return types of un-defaulted nullary methods (which can be overloaded but rarely are). If we could use only those limited cases to guess the appropriate types, then plug them in and see if they typecheck, that would go a long way towards softening the blow of removing associated type inference.
So, in summary:
• I think that removing associated type inference will seriously impair Collection's usability and type-safety.
• I think that these issues ought to be mitigated in the future by new compiler features which we may not have the time to implement before we ship Swift 3.
So I think this change should be deferred to Swift 4, when we'll have time to add mitigating features. (Or, if you want to add mitigating features, merging this change should be conditioned on the mitigating features being finished too.) If we do it now, we will be breaking code which we will later un-break, and exposing chinks in our protocols' armor which we will later fix. Let's be patient.
> * Is the problem being addressed significant enough to warrant a change to Swift?
Yes, but I don't think it's significant enough to warrant a change in Swift *3*.
> * Does this proposal fit well with the feel and direction of Swift?
Yes and no; see above.
> * If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
> * How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
Much more than I probably should have. :^)
More information about the swift-evolution