[Pitch] Remove associated type inference

No, I'm suggesting to limit the scope.

protocol Collection {
  typealias Index
  @infers(Index)
  var startIndex: Index { get }
  var endIndex: Index { get }
  subscript(i: Index) -> Iterator.Element
}

Here, only 'var startIndex' in a conforming type would be causing 'Index'
to be inferred. 'endIndex' and subscript won't have any effect on the
inference. My suggestion is that we will only allow one such declaration
to exist. This is a much simpler problem, I think, than solving a
constraint system that involves all declarations that mention Index (as it
is now).

Dmitri

···

On Wed, May 25, 2016 at 3:42 PM, Leonardo Pessoa <me@lmpessoa.com> wrote:

On Wednesday, 25 May 2016, Dmitri Gribenko via swift-evolution < > swift-evolution@swift.org> wrote:

On Wed, May 25, 2016 at 2:52 PM, David Hart <david@hartbit.com> wrote:
>
>> On 25 May 2016, at 23:47, Dmitri Gribenko <gribozavr@gmail.com> wrote:
>>
>> On Wed, May 25, 2016 at 2:43 PM, David Hart via swift-evolution >> >> <swift-evolution@swift.org> wrote:
>>> Impact on Existing Code
>>>
>>> This is a breaking change that will require conforming types which
relied on
>>> the inference, including in the Standard Library, to explicitly
declare
>>> associated types. A Fix-It could be introduced to add the typealias
and
>>> leave the type to be filled in. That way, all the type inference
could be
>>> removed from the compiler.
>>
>> Please show an example -- for example, what a smallest collection type
>> will look like.
>
> Isn’t that the example in the Detailed Design section? What other
example were you thinking of?

You are showing an iterator. Try doing a collection, it has many more
associated types most of which are defaulted.

>>> Alternatives Considered
>>>
>>> The only alternative is to keep the inference with the known
consequences on
>>> the compiler.
>>
>> Sorry, that's not fair :) There is a middle ground -- limited
>> inference. For example, in Collection, we don't need Index to be
>> inferrable from every declaration that mentions it. We can add a
>> feature to declare that the type of 'var startIndex' infers
>> 'associatedtype Index' (via an appropriate attribute). It is true
>> that this approach would not remove global inference as such, but it
>> will make it a much easier problem I believe.
>
> This sounds like a more complicated solution: it does not remove global
inference and complicates the language with an additional attribute only to
help the compiler. I don’t see many advantages to this solution.

The advantage is that we can keep the boilerplate down, and make the
problem easier in the compiler.

If the issue is easing the work of the compiler, are you suggesting
dropping the entire type inference? I don't really think removing it here
will "solve" anything.

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

>
>>
>>> Impact on Existing Code
>>>
>>> This is a breaking change that will require conforming types which relied on
>>> the inference, including in the Standard Library, to explicitly declare
>>> associated types. A Fix-It could be introduced to add the typealias and
>>> leave the type to be filled in. That way, all the type inference could be
>>> removed from the compiler.
>>
>> Please show an example -- for example, what a smallest collection type
>> will look like.
>
> Isn’t that the example in the Detailed Design section? What other example were you thinking of?

You are showing an iterator. Try doing a collection, it has many more
associated types most of which are defaulted.

>>> Alternatives Considered
>>>
>>> The only alternative is to keep the inference with the known consequences on
>>> the compiler.
>>
>> Sorry, that's not fair :) There is a middle ground -- limited
>> inference. For example, in Collection, we don't need Index to be
>> inferrable from every declaration that mentions it. We can add a
>> feature to declare that the type of 'var startIndex' infers
>> 'associatedtype Index' (via an appropriate attribute). It is true
>> that this approach would not remove global inference as such, but it
>> will make it a much easier problem I believe.
>
> This sounds like a more complicated solution: it does not remove global inference and complicates the language with an additional attribute only to help the compiler. I don’t see many advantages to this solution.

The advantage is that we can keep the boilerplate down, and make the
problem easier in the compiler.

If the issue is easing the work of the compiler, are you suggesting dropping the entire type inference? I don't really think removing it here will "solve" anything.

No, I'm suggesting to limit the scope.

protocol Collection {
  typealias Index
  @infers(Index)
  var startIndex: Index { get }
  var endIndex: Index { get }
  subscript(i: Index) -> Iterator.Element
}

Here, only 'var startIndex' in a conforming type would be causing 'Index' to be inferred. 'endIndex' and subscript won't have any effect on the inference. My suggestion is that we will only allow one such declaration to exist. This is a much simpler problem, I think, than solving a constraint system that involves all declarations that mention Index (as it is now).

And IMO it's much more acceptable to do something like this that only impacts protocol declarations than to remove associated type inference altogether and place a burden on every conformance.

···

Sent from my iPad

On May 25, 2016, at 6:11 PM, Dmitri Gribenko via swift-evolution <swift-evolution@swift.org> wrote:

On Wed, May 25, 2016 at 3:42 PM, Leonardo Pessoa <me@lmpessoa.com> wrote:

On Wednesday, 25 May 2016, Dmitri Gribenko via swift-evolution <swift-evolution@swift.org> wrote:
On Wed, May 25, 2016 at 2:52 PM, David Hart <david@hartbit.com> wrote:
>> On 25 May 2016, at 23:47, Dmitri Gribenko <gribozavr@gmail.com> wrote:
>> On Wed, May 25, 2016 at 2:43 PM, David Hart via swift-evolution >>> >> <swift-evolution@swift.org> wrote:

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

>
>>
>>> Impact on Existing Code
>>>
>>> This is a breaking change that will require conforming types which
relied on
>>> the inference, including in the Standard Library, to explicitly declare
>>> associated types. A Fix-It could be introduced to add the typealias and
>>> leave the type to be filled in. That way, all the type inference could
be
>>> removed from the compiler.
>>
>> Please show an example -- for example, what a smallest collection type
>> will look like.
>
> Isn’t that the example in the Detailed Design section? What other
example were you thinking of?

You are showing an iterator. Try doing a collection, it has many more
associated types most of which are defaulted.

>>> Alternatives Considered
>>>
>>> The only alternative is to keep the inference with the known
consequences on
>>> the compiler.
>>
>> Sorry, that's not fair :) There is a middle ground -- limited
>> inference. For example, in Collection, we don't need Index to be
>> inferrable from every declaration that mentions it. We can add a
>> feature to declare that the type of 'var startIndex' infers
>> 'associatedtype Index' (via an appropriate attribute). It is true
>> that this approach would not remove global inference as such, but it
>> will make it a much easier problem I believe.
>
> This sounds like a more complicated solution: it does not remove global
inference and complicates the language with an additional attribute only to
help the compiler. I don’t see many advantages to this solution.

The advantage is that we can keep the boilerplate down, and make the
problem easier in the compiler.

If the issue is easing the work of the compiler, are you suggesting
dropping the entire type inference? I don't really think removing it here
will "solve" anything.

···

On Wednesday, 25 May 2016, Dmitri Gribenko via swift-evolution < swift-evolution@swift.org> wrote:

On Wed, May 25, 2016 at 2:52 PM, David Hart <david@hartbit.com > <javascript:;>> wrote:
>> On 25 May 2016, at 23:47, Dmitri Gribenko <gribozavr@gmail.com > <javascript:;>> wrote:
>> On Wed, May 25, 2016 at 2:43 PM, David Hart via swift-evolution > >> <swift-evolution@swift.org <javascript:;>> wrote:

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com
<javascript:;>>*/
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <javascript:;>
https://lists.swift.org/mailman/listinfo/swift-evolution

--

I'm not quite sure I follow you. I am suggesting only removing it for associated type inference, where we fairly rarely benefit from it compared to general type inference.

···

On 26 May 2016, at 00:42, Leonardo Pessoa <me@lmpessoa.com> wrote:

If the issue is easing the work of the compiler, are you suggesting dropping the entire type inference? I don't really think removing it here will "solve" anything.

We could have the generic type parameter always shadow the associated type.

···

On 26 May 2016, at 06:08, Patrick Smith <pgwsmith@gmail.com> wrote:

While this has been a handy feature, I don’t mind making things more explicit, as I think it helps communication. Sometimes clarity that helps the compiler will also help the reader. It’s only really convenient when writing.

I would be happy with this change as long as the issue with same named generics were changed. Currently in Swift 2.2 I can’t do this:

struct SomeGenericGenerator<Element> : GeneratorType {
  typealias Element = Element // Error: Type alias ‘Element’ circularly references itself
}

It’s a real pain, as now I have to think up some alternate name for the generic parameter ‘Element’.

Whereas, with automatic inference, I can do this without the compiler complaining:

struct SomeGenericGenerator<Element> : GeneratorType {
  mutating func next() -> Element? {
    return nil
  }
}

So I’d like to see the above `typealias Element = Element` allowed if possible.

On 26 May 2016, at 7:43 AM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

Here’s a pitch for removing associated type inference as per the Generics Manifesto. If we want to do it, we’d better do it before Swift 3:

Remove associated type inference
Proposal: SE-XXXX
Author: David Hart, Douglas Gregor
Status: TBD
Review manager: TBD
Introduction

This proposal seeks to remove the inference of associated types in types conforming to protocols.

Motivation

Even if associated types inference in a useful feature, it is also a big source of bugs in the compiler. This proposal argues that the usefulness does not outweight its architectural complexity. As per the Generics Manifesto:

associated type inference is the only place in Swift where we have a global type inference problem: it has historically been a major source of bugs, and implementing it fully and correctly requires a drastically different architecture to the type checker.
Because this is a breaking change, it would be beneficial to implement it for Swift 3.

Detailed Design

The proposal would remove associated type inference and make code which relied on it invalid:

protocol IteratorProtocol {
  associatedtype Element
  mutating func next() -> Element?
}

struct IntIterator : IteratorProtocol {
  mutating func next() -> Int? { ... } // used to infer Element = Int
}
The compiler would generate an error message stating: error: IntIterator is missing its Element associated type declaration. The code would have to be modified as follows to fix the error:

struct IntIterator : IteratorProtocol {
    typealias Element = Int
    mutating func next() -> Int? { return nil } // used to infer Element = Int
}
Impact on Existing Code

This is a breaking change that will require conforming types which relied on the inference, including in the Standard Library, to explicitly declare associated types. A Fix-It could be introduced to add the typealias and leave the type to be filled in. That way, all the type inference could be removed from the compiler.

Alternatives Considered

The only alternative is to keep the inference with the known consequences on the compiler.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

We could have the generic type parameter always shadow the associated type.

I believe there has been talk of automatically introducing an associated type corresponding to generic parameters. I'm not sure where that stands but IIRC it was someone from the core team that was considering it.

···

Sent from my iPad

On May 26, 2016, at 1:21 AM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

On 26 May 2016, at 06:08, Patrick Smith <pgwsmith@gmail.com> wrote:

While this has been a handy feature, I don’t mind making things more explicit, as I think it helps communication. Sometimes clarity that helps the compiler will also help the reader. It’s only really convenient when writing.

I would be happy with this change as long as the issue with same named generics were changed. Currently in Swift 2.2 I can’t do this:

struct SomeGenericGenerator<Element> : GeneratorType {
  typealias Element = Element // Error: Type alias ‘Element’ circularly references itself
}

It’s a real pain, as now I have to think up some alternate name for the generic parameter ‘Element’.

Whereas, with automatic inference, I can do this without the compiler complaining:

struct SomeGenericGenerator<Element> : GeneratorType {
  mutating func next() -> Element? {
    return nil
  }
}

So I’d like to see the above `typealias Element = Element` allowed if possible.

On 26 May 2016, at 7:43 AM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

Here’s a pitch for removing associated type inference as per the Generics Manifesto. If we want to do it, we’d better do it before Swift 3:

Remove associated type inference
Proposal: SE-XXXX
Author: David Hart, Douglas Gregor
Status: TBD
Review manager: TBD
Introduction

This proposal seeks to remove the inference of associated types in types conforming to protocols.

Motivation

Even if associated types inference in a useful feature, it is also a big source of bugs in the compiler. This proposal argues that the usefulness does not outweight its architectural complexity. As per the Generics Manifesto:

associated type inference is the only place in Swift where we have a global type inference problem: it has historically been a major source of bugs, and implementing it fully and correctly requires a drastically different architecture to the type checker.
Because this is a breaking change, it would be beneficial to implement it for Swift 3.

Detailed Design

The proposal would remove associated type inference and make code which relied on it invalid:

protocol IteratorProtocol {
  associatedtype Element
  mutating func next() -> Element?
}

struct IntIterator : IteratorProtocol {
  mutating func next() -> Int? { ... } // used to infer Element = Int
}
The compiler would generate an error message stating: error: IntIterator is missing its Element associated type declaration. The code would have to be modified as follows to fix the error:

struct IntIterator : IteratorProtocol {
    typealias Element = Int
    mutating func next() -> Int? { return nil } // used to infer Element = Int
}
Impact on Existing Code

This is a breaking change that will require conforming types which relied on the inference, including in the Standard Library, to explicitly declare associated types. A Fix-It could be introduced to add the typealias and leave the type to be filled in. That way, all the type inference could be removed from the compiler.

Alternatives Considered

The only alternative is to keep the inference with the known consequences on the compiler.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

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

Agree. The self documenting nature of this is definitely welcome.

···

On Thu, May 26, 2016, at 02:26 AM, David Hart via swift-evolution wrote:

I believe it also helps readability. Associated type are part of the
declaration and I think it's worth pursuing better readability than
programmer friendliness at the declaration. When reading a type
declaration that conforms to a protocol with associated types, I find
it refreshing not having to hunt down the function declaration to
figure out what type was inferred as the associated type. I prefer it
when programmers are explicit in this situation.

Here’s a pitch for removing associated type inference as per the Generics
Manifesto. If we want to do it, we’d better do it before Swift 3:

Remove associated type inference

   - Proposal: SE-XXXX
   <https://github.com/apple/swift-evolution/blob/master/proposals/XXXX-remove-associated-type-inference.md&gt;
   - Author: David Hart <https://github.com/hartbit&gt;, Douglas Gregor
   <https://github.com/DougGregor&gt;
   - Status: TBD
   - Review manager: TBD

<https://github.com/hartbit/swift-evolution/blob/remove-associated-type-inference/proposals/XXXX-remove-associated-type-inference.md#introduction&gt;
Introduction

This proposal seeks to remove the inference of associated types in types
conforming to protocols.

<https://github.com/hartbit/swift-evolution/blob/remove-associated-type-inference/proposals/XXXX-remove-associated-type-inference.md#motivation&gt;
Motivation

Even if associated types inference in a useful feature, it is also a big
source of bugs in the compiler. This proposal argues that the usefulness
does not outweight its architectural complexity. As per the Generics
Manifesto
<https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md&gt;:

associated type inference is the only place in Swift where we have a
global type inference problem: it has historically been a major source of
bugs, and implementing it fully and correctly requires a drastically
different architecture to the type checker.

Because this is a breaking change, it would be beneficial to implement it
for Swift 3.

<https://github.com/hartbit/swift-evolution/blob/remove-associated-type-inference/proposals/XXXX-remove-associated-type-inference.md#detailed-design&gt;Detailed
Design

The proposal would remove associated type inference and make code which
relied on it invalid:

protocol IteratorProtocol {
  associatedtype Element
  mutating func next() -> Element?
}
struct IntIterator : IteratorProtocol {
  mutating func next() -> Int? { ... } // used to infer Element = Int
}

The compiler would generate an error message stating: error: IntIterator
is missing its Element associated type declaration. The code would have
to be modified as follows to fix the error:

From a purely english syntax viewpoint, i would prefer the error to be
along the lines of

IntIterator is missing a declaration for the Element associated type

Or

IntIterator is missing a declaration for its Element associated type

Clearer still:

"IntIterator is missing a declaration for its associated type Element"

···

On Thu, May 26, 2016 at 12:47 PM, L. Mihalkovic via swift-evolution < swift-evolution@swift.org> wrote:

On May 25, 2016, at 11:43 PM, David Hart via swift-evolution < > swift-evolution@swift.org> wrote:

struct IntIterator : IteratorProtocol {
    typealias Element = Int
    mutating func next() -> Int? { return nil } // used to infer Element = Int
}

<https://github.com/hartbit/swift-evolution/blob/remove-associated-type-inference/proposals/XXXX-remove-associated-type-inference.md#impact-on-existing-code&gt;Impact
on Existing Code

This is a breaking change that will require conforming types which relied
on the inference, including in the Standard Library, to explicitly declare
associated types. A Fix-It could be introduced to add the typealias and
leave the type to be filled in. That way, all the type inference could be
removed from the compiler.

<https://github.com/hartbit/swift-evolution/blob/remove-associated-type-inference/proposals/XXXX-remove-associated-type-inference.md#alternatives-considered&gt;Alternatives
Considered
The only alternative is to keep the inference with the known consequences
on the compiler.

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

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