[Review] SE-0108: Remove associated type inference


(Chris Lattner) #1

Hello Swift community,

The review of "SE-0108: Remove associated type inference" begins now and runs through July 4. The proposal is available here:

  https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

  https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to the review manager.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and contribute to the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

  * What is your evaluation of the proposal?
  * Is the problem being addressed significant enough to warrant a change to Swift?
  * Does this proposal fit well with the feel and direction of Swift?
  * 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?

More information about the Swift evolution process is available at

  https://github.com/apple/swift-evolution/blob/master/process.md

Thank you,

-Chris Lattner
Review Manager


(Russ Bishop) #2

Hello Swift community,

The review of "SE-0108: Remove associated type inference" begins now and runs through July 4. The proposal is available here:

  https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md

  * What is your evaluation of the proposal?

I don’t like the change to using typealias for explicitly binding the type because typealias already has another completely different meaning (introducing a new name) in the identical context. This smacks of the same problem associated types had back when they were spelled typealias. I also understand why using associatedtype is problematic. We do have a keyword that indicates “this thing is not completely new, but actually replaces the received member”

override associatedtype Element = String

Maybe the objection is verbosity? But it certainly is extremely clear that Element is not a new name being introduced, nor is it introducing a new associatedtype. You could also use “let associatedtype Element = String” if override is too tied up with class inheritance.

Binding using a nested type seems odd, though I don’t necessarily object to it.

If associated type inference were to be removed, C.A would be bound as Int (since there would be no explicit typealias declaration overriding the default type value), and the doSomething() implementation returning Int would be considered to fulfill the protocol requirement. Thus, the semantics of the code listing above would change even though the source itself remained unchanged.

This is problematic to me. This proposal introduces the disambiguation syntax so I would say that the compiler should emit an error if this situation arises and require you to explicitly specify what associated type you are binding, ignoring the protocol’s default. It could still warn on doSomething() to let you know there is a potential pitfall.

  * Is the problem being addressed significant enough to warrant a change to Swift?

I believe Doug when he says it has negative implications for the type checker.

  * Does this proposal fit well with the feel and direction of Swift?
  * How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Reading and thinking, following the original discussion thread.

···

On Jun 29, 2016, at 12:33 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:


(Brent Royal-Gordon) #3

  https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md

  * 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?

N/A.

  * 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. :^)

···

--
Brent Royal-Gordon
Architechies


(Matthew Johnson) #4

  * What is your evaluation of the proposal?

I’m going to stay neutral. The motivation is implementation focused and I am not qualified to adequately assess it.

It does sound like it might be necessary to do this (at least temporarily) in order to facilitate evolution of other generics features. However, as I stated in the discussion, I do consider it unfortunate. The language has this feature for a good reason and that hasn’t changed. If we do remove this feature we should be very certain that it is necessary.

  * Is the problem being addressed significant enough to warrant a change to Swift?

It sounds like the implementation complexities are significant enough to warrant a change. I trust the core team to asses that.

If it weren’t for implementation considerations I wouldn’t believe there is a problem. I think associated type inference is a particularly elegant feature, not a problem.

  * Does this proposal fit well with the feel and direction of Swift?

I suppose it does in the sense that a major them of Swift 3 is to clean up areas of the language that didn’t work out as hoped or intended.

  * If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

I have not actively used them in real projects, but I have spent significant time studying functional languages where inference is a hallmark feature. Inference can be an extremely elegant feature. It can also be pushed too far when it can hinder clarity and readability.

Swift attempts to strike a careful balance here and does a pretty good job of it. However, there is *no* case where I think Swift takes inference too far (in terms of impact on clarity and readability), including associated type inference. Reducing Swift’s inference capabilities feels like a step backwards to me. I believe associated type inference *increases* clarity and readability.

It’s worth pointing out that manually providing associated type bindings is valid in Swift today, yet it is rare to do so explicitly using a typealias when implementing a conformance. I believe this is anecdotal evidence that the community generally finds that leaning on inference of associated types *increases* clarity and readability and values this feature.

  * How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Careful consideration of the implementation issues, the proposed solution, and the impact on users of the language.

···

More information about the Swift evolution process is available at

  https://github.com/apple/swift-evolution/blob/master/process.md

Thank you,

-Chris Lattner
Review Manager

_______________________________________________
swift-evolution-announce mailing list
swift-evolution-announce@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution-announce


(Jordan Rose) #5

[Proposal: https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md ]

I’m pretty concerned about completely removing this feature. Yes, it’s a type-checker / decl-checker nightmare, but I think Paolo’s example in the initial discussion showed how it’s being used effectively today. I’d much rather have some kind of inference marker that maps one-to-one between an associated type and a value requirement (method, initializer, property, or subscript), also as brought up in the original discussion.

protocol OptionA {
  associatedtype Index

  @infers(Index)
  var startIndex: Index { get }

  var endIndex: Index { get }
}

protocol OptionB {
  @inferredFrom(startIndex) // allows a full name here for overload resolution
  associatedtype Index

  var startIndex: Index { get }
  var endIndex: Index { get }
}

protocol OptionC {
  associatedtype Index in startIndex // sugar

  var startIndex: Index { get }
  var endIndex: Index { get }
}

OptionC is the prettiest, but OptionA is probably the most flexible (consider overloading on associated types).

I know we want to lock down on things now, and I know we can do better in the future, but I think inferring associated types is really quite common, and I’m concerned about taking it out without giving people a good alternative. This is just an impression, though.

Jordan


(Russ Bishop) #6

I’m curious about this too. It seems too easy...

Russ

···

On Jun 29, 2016, at 4:38 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

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.


(Douglas Gregor) #7

  https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md

  * 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.

The usability argument I understand. It’s a big, open question. I hacked up a flag for swiftc (-Xfrontend -disable-associated-type-witness-inference) on this branch:

  https://github.com/apple/swift/tree/disable-associated-type-witness-inference

that simply disables associated type witness inference so we can experiment. If we do nothing to the standard library, the experience is awful for (e.g.) the case of a type that minimally conforms to today’s Collection. But we knew the standard library would need changes, because it heavily depends on this inference today, so we won’t have a good sense of what we can accomplish until someone actually tries to work with the proposed restriction. I, personally, don’t have the time to invest in this right now :frowning:

• 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.

You're talking about recursive protocol constraints (which would help collapse some of the underscored protocols) and where clauses on associated types in particular?

  - Doug

···

On Jun 29, 2016, at 4:38 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:


(TJ Usiyan) #8

* What is your evaluation of the proposal?
+ 1
        * Is the problem being addressed significant enough to warrant a
change to Swift?
Yes. When inference goes wrong it is frustrating and difficult to puzzle
out.
        * Does this proposal fit well with the feel and direction of Swift?
Yes. I agree that a keyword for explicitly invoking inference would also
work if it meant that the process would be consistent. The ability to add
type aliases to protocol extensions is welcome as well.
        * 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?
A couple readings.

···

On Thu, Jun 30, 2016 at 7:23 PM, Jordan Rose via swift-evolution < swift-evolution@swift.org> wrote:

[Proposal:
https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md
]

I’m pretty concerned about completely removing this feature. Yes, it’s a
type-checker / decl-checker nightmare, but I think Paolo’s example in the
initial discussion showed how it’s being used effectively today. I’d much
rather have some kind of inference marker that maps one-to-one between an
associated type and a value requirement (method, initializer, property, or
subscript), also as brought up in the original discussion.

protocol OptionA {
  associatedtype Index

  @infers(Index)
  var startIndex: Index { get }

  var endIndex: Index { get }
}

protocol OptionB {
  @inferredFrom(startIndex) // allows a full name here for overload
resolution
  associatedtype Index

  var startIndex: Index { get }
  var endIndex: Index { get }
}

protocol OptionC {
  associatedtype Index in startIndex // sugar

  var startIndex: Index { get }
  var endIndex: Index { get }
}

OptionC is the prettiest, but OptionA is probably the most flexible
(consider overloading on associated types).

I know we want to lock down on things now, and I know we can do better in
the future, but I think inferring associated types is really quite common,
and I’m concerned about taking it out without giving people a good
alternative. This *is* just an impression, though.

Jordan

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Russ Bishop) #9

I’m trying to fill a gap in my own knowledge here. How does explicitly stating that startIndex is the inference point for Index help?

Is it because various extensions and default implementations can provide different concrete types for Index, so the type checker is trying to resolve the ambiguity? If that’s the case, specifying startIndex here restricts the defaults/extensions that need to be considered from all to just ones that implement startIndex? Is that good enough generally or does it just solve the standard library’s problems?

Would it be enough to have rules along these lines for a concrete type adopting a protocol with associated types?

1. If the type’s main declaration (not defaults or extensions) contains a member satisfying a protocol requirement (where the requirement is specified in terms of an associated type) the associated type is locked to the type used in that member, so no global inference is necessary. If more than one such member is present all must use the same exact type.
2. Otherwise if there exists only one default/extension satisfying the associated type, the type used in that default implementation is used.
3. In all other cases the user must specify the associated types explicitly.

Apologies if this is stuff I should already know.

Russ

···

On Jun 30, 2016, at 4:23 PM, Jordan Rose via swift-evolution <swift-evolution@swift.org> wrote:

[Proposal: https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md ]

I’m pretty concerned about completely removing this feature. Yes, it’s a type-checker / decl-checker nightmare, but I think Paolo’s example in the initial discussion showed how it’s being used effectively today. I’d much rather have some kind of inference marker that maps one-to-one between an associated type and a value requirement (method, initializer, property, or subscript), also as brought up in the original discussion.

protocol OptionA {
  associatedtype Index

  @infers(Index)
  var startIndex: Index { get }

  var endIndex: Index { get }
}

protocol OptionB {
  @inferredFrom(startIndex) // allows a full name here for overload resolution
  associatedtype Index

  var startIndex: Index { get }
  var endIndex: Index { get }
}

protocol OptionC {
  associatedtype Index in startIndex // sugar

  var startIndex: Index { get }
  var endIndex: Index { get }
}

OptionC is the prettiest, but OptionA is probably the most flexible (consider overloading on associated types).

I know we want to lock down on things now, and I know we can do better in the future, but I think inferring associated types is really quite common, and I’m concerned about taking it out without giving people a good alternative. This is just an impression, though.

Jordan
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Brent Royal-Gordon) #10

I'm also talking about "caveman inference" if that's judged to be a good idea for usability, and anything else we need to make associated types ergonomic despite the loss of inference. (One underdeveloped thought I just had: keep the inference engine around and use it to suggest fix-its for unspecified associated types.)

Ultimately what I'm saying is this: Removing associated type inference is going to impact a lot of code. We can see the impact in the standard library, but we must also remember that it will impact user code, and users will not have Dave Abrahams around to redesign their protocols for them.

Now, the standard library *is* a bit of a special case: In some areas—particularly Collection and its ilk—it is very aggressively designed right to the ragged edge of what Swift supports. But in other areas, it is the canary in the coal mine. If we find that, say, FloatingPoint is significantly more burdensome to conform to without redesigning it, that means many protocols in user code will be too.

Normally, we ship things incrementally, but here I think we need to make an exception: This proposal will make a gigantic mess, and we cannot ship it until we've cleaned that mess up. That means we ought to think long and hard, right now, about whether September is a reasonable deadline to not only rip out associated types, not only redesign the standard library to clean up the problems it creates, but also add whatever features are necessary to compensate for the removal. And if we don't think we can, we should defer until we have the time to finish the job.

···

On Jun 29, 2016, at 10:55 PM, Douglas Gregor <dgregor@apple.com> wrote:

You're talking about recursive protocol constraints (which would help collapse some of the underscored protocols) and where clauses on associated types in particular?

--
Brent Royal-Gordon
Architechies


(Jordan Rose) #11

I don't remember exactly how the current rules work, but I think the compiler looks at all the members that mention an associated type and tries to figure out if they're all in sync. Reducing that to just looking at one value requirement might be enough to satisfy Doug's concerns, even if it still has to do overload resolution…or you could follow the spirit of your rule 2 and say that any overloads force you to specify the element type explicitly.

Rule 1, however, is the important one: "if more than one such member is present all must use the same exact type". I think that's already moving into the realm of spooky action and circularity issues that Doug's attempting to squash.

Jordan

···

On Jul 1, 2016, at 15:53, Russ Bishop <xenadu@gmail.com> wrote:

On Jun 30, 2016, at 4:23 PM, Jordan Rose via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

[Proposal: https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md ]

I’m pretty concerned about completely removing this feature. Yes, it’s a type-checker / decl-checker nightmare, but I think Paolo’s example in the initial discussion showed how it’s being used effectively today. I’d much rather have some kind of inference marker that maps one-to-one between an associated type and a value requirement (method, initializer, property, or subscript), also as brought up in the original discussion.

protocol OptionA {
  associatedtype Index

  @infers(Index)
  var startIndex: Index { get }

  var endIndex: Index { get }
}

protocol OptionB {
  @inferredFrom(startIndex) // allows a full name here for overload resolution
  associatedtype Index

  var startIndex: Index { get }
  var endIndex: Index { get }
}

protocol OptionC {
  associatedtype Index in startIndex // sugar

  var startIndex: Index { get }
  var endIndex: Index { get }
}

OptionC is the prettiest, but OptionA is probably the most flexible (consider overloading on associated types).

I know we want to lock down on things now, and I know we can do better in the future, but I think inferring associated types is really quite common, and I’m concerned about taking it out without giving people a good alternative. This is just an impression, though.

Jordan
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I’m trying to fill a gap in my own knowledge here. How does explicitly stating that startIndex is the inference point for Index help?

Is it because various extensions and default implementations can provide different concrete types for Index, so the type checker is trying to resolve the ambiguity? If that’s the case, specifying startIndex here restricts the defaults/extensions that need to be considered from all to just ones that implement startIndex? Is that good enough generally or does it just solve the standard library’s problems?

Would it be enough to have rules along these lines for a concrete type adopting a protocol with associated types?

1. If the type’s main declaration (not defaults or extensions) contains a member satisfying a protocol requirement (where the requirement is specified in terms of an associated type) the associated type is locked to the type used in that member, so no global inference is necessary. If more than one such member is present all must use the same exact type.
2. Otherwise if there exists only one default/extension satisfying the associated type, the type used in that default implementation is used.
3. In all other cases the user must specify the associated types explicitly.


(Douglas Gregor) #12

[Proposal: https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md ]

I’m pretty concerned about completely removing this feature. Yes, it’s a type-checker / decl-checker nightmare, but I think Paolo’s example in the initial discussion showed how it’s being used effectively today. I’d much rather have some kind of inference marker that maps one-to-one between an associated type and a value requirement (method, initializer, property, or subscript), also as brought up in the original discussion.

protocol OptionA {
  associatedtype Index

  @infers(Index)
  var startIndex: Index { get }

  var endIndex: Index { get }
}

protocol OptionB {
  @inferredFrom(startIndex) // allows a full name here for overload resolution
  associatedtype Index

  var startIndex: Index { get }
  var endIndex: Index { get }
}

protocol OptionC {
  associatedtype Index in startIndex // sugar

  var startIndex: Index { get }
  var endIndex: Index { get }
}

OptionC is the prettiest, but OptionA is probably the most flexible (consider overloading on associated types).

I know we want to lock down on things now, and I know we can do better in the future, but I think inferring associated types is really quite common, and I’m concerned about taking it out without giving people a good alternative. This is just an impression, though.

Jordan
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I’m trying to fill a gap in my own knowledge here. How does explicitly stating that startIndex is the inference point for Index help?

Is it because various extensions and default implementations can provide different concrete types for Index, so the type checker is trying to resolve the ambiguity? If that’s the case, specifying startIndex here restricts the defaults/extensions that need to be considered from all to just ones that implement startIndex? Is that good enough generally or does it just solve the standard library’s problems?

Would it be enough to have rules along these lines for a concrete type adopting a protocol with associated types?

1. If the type’s main declaration (not defaults or extensions) contains a member satisfying a protocol requirement (where the requirement is specified in terms of an associated type) the associated type is locked to the type used in that member, so no global inference is necessary. If more than one such member is present all must use the same exact type.
2. Otherwise if there exists only one default/extension satisfying the associated type, the type used in that default implementation is used.
3. In all other cases the user must specify the associated types explicitly.

I don't remember exactly how the current rules work, but I think the compiler looks at all the members that mention an associated type and tries to figure out if they're all in sync. Reducing that to just looking at one value requirement might be enough to satisfy Doug's concerns, even if it still has to do overload resolution…or you could follow the spirit of your rule 2 and say that any overloads force you to specify the element type explicitly.

The compiler currently looks at all of the requirements that mention any of the associated types, then matches each requirement up to all potential declarations that might satisfy the requirement (whether they come from the concrete type, its extensions, or some protocol extension doesn’t matter) to infer potential types for each associated type requirement. A potential solution to the problem assigns a type for each associated type requirement, which then needs to be checked as a whole (e.g., did the type we infer for SubSequence meet the Sequence requirement, and is its Element type the same as our Element type?). When there are multiple possible solutions, they’re ranked based on which declarations were used to satisfy a particular requirement—a declaration from the concrete type is usually better than one from a protocol extension, for example—so one solution can be chosen.

And, really, you should be doing this for all protocol conformances at once, because they often share associated type names. That’s not implemented.

So, back to the restriction: it certainly does help to only be considering one *requirement* for each inferrable associated type, but you’re still considering each possible declaration that can satisfy that requirement. It reduces the state space, but you’re still looking at complete solutions across several associated types and potential declarations that satisfy each requirement we inferred from.

Rule 1, however, is the important one: "if more than one such member is present all must use the same exact type". I think that's already moving into the realm of spooky action and circularity issues that Doug's attempting to squash.

We already implement Rule 1.

  - Doug

···

On Jul 6, 2016, at 10:43 AM, Jordan Rose <jordan_rose@apple.com> wrote:

On Jul 1, 2016, at 15:53, Russ Bishop <xenadu@gmail.com <mailto:xenadu@gmail.com>> wrote:

On Jun 30, 2016, at 4:23 PM, Jordan Rose via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: