[swift-evolution] [Pitch] Simpler interpretation of a reference to a generic type with no arguments

Xiaodi Wu xiaodi.wu at gmail.com
Thu Jun 23 15:46:45 CDT 2016


Cool--no opposition here!
On Thu, Jun 23, 2016 at 15:43 Slava Pestov <spestov at apple.com> wrote:

> On Jun 23, 2016, at 1:39 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
> Good to know. I absolutely agree that the gains to be had here wouldn't be
> worth a one-off hack.
>
>
> If people are strongly (or even mildly) opposed to removing this rule, we
> can give some thought to a more general solution. I don’t feel very
> strongly about this proposal one way or another, it’s just a bit of ugly
> code in TypeCheckType.cpp that would be nice to remove, and a developer on
> Twitter recently noticed this behavior and found it surprising.
>
> On Thu, Jun 23, 2016 at 15:36 Slava Pestov <spestov at apple.com> wrote:
>
>> On Jun 23, 2016, at 1:34 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>
>> Sorry, it's I who is saying things all wrong. I meant to ask, is it
>> feasible to keep both behaviors but have #2 "win" over #1, instead of
>> getting rid of behavior #1 entirely?
>>
>>
>> I suspect there might be some way, but I think it would have to be some
>> kind of one-off hack, which is not in line with our long-term goal of
>> making the type checker more maintainable and correct ‘by construction’.
>>
>>
>> On Thu, Jun 23, 2016 at 15:30 Slava Pestov <spestov at apple.com> wrote:
>>
>>> On Jun 23, 2016, at 1:27 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>
>>> When you mention the difficulty of an alternative, is that to say that
>>> it's not feasible for the GenericBox in the last example to be resolved as
>>> GenericBox<T>? From an end-user point of view, that seems to be the most
>>> sensible behavior.
>>>
>>>
>>> With my proposed change, GenericBox would be resolved as GenericBox<T>
>>> in the last example. Right now it fails to type check.
>>>
>>> Here is an example that works right now, but would not work with my
>>> proposed change:
>>>
>>> struct GenericBox<Contents> {
>>> // Currently Swift resolves this as ‘GenericBox<Contents>’
>>> // With the new rule, we cannot infer the parameter, because there’s no
>>> expression to infer it from
>>> func combine(other: GenericBox) {
>>>>>> }
>>> }
>>>
>>> Basically the meaning of ‘GenericBox’ right now depends on whether it
>>> appears inside its own definition or extension thereof, or not. The
>>> behavior when it appears elsewhere is more general — we infer the
>>> parameters from the surrounding expression, instead of assuming they’re
>>> equal to the context parameters.
>>>
>>> This is a subtle change — definitely let me know if I’m not explaining
>>> it well.
>>>
>>> Slava
>>>
>>> On Thu, Jun 23, 2016 at 15:14 Slava Pestov via swift-evolution <
>>> swift-evolution at swift.org> wrote:
>>>
>>>> Simpler interpretation of a reference to a generic type with no
>>>> arguments
>>>>
>>>>    - Proposal: SE-9999
>>>>    <https://github.com/slavapestov/swift-evolution/blob/silly-proposals/proposals/9999-simplify-unbound-generic-type.md>
>>>>    - Author: Slava Pestov <https://github.com/slavapestov>
>>>>    - Status: Awaiting review
>>>>    - Review manager: TBD
>>>>
>>>>
>>>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#introduction>
>>>> Introduction
>>>>
>>>> This proposal cleans up the semantics of a reference to a generic type
>>>> when no generic arguments are applied.
>>>>
>>>> Swift-evolution thread: Discussion thread topic for that proposal
>>>> <http://news.gmane.org/gmane.comp.lang.swift.evolution>
>>>>
>>>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#motivation>
>>>> Motivation
>>>>
>>>> Right now, we allow a generic type to be referenced with no generic
>>>> arguments applied in a handful of special cases. The two primary rules here
>>>> are the following:
>>>>
>>>>    -
>>>>
>>>>    If the scope from which the reference is made is nested inside the
>>>>    definition of the type or an extension thereof, omitting generic arguments
>>>>    just means to implicitly apply the arguments from context.
>>>>
>>>>    For example,
>>>>
>>>> struct GenericBox<Contents> {
>>>>   let contents: Contents
>>>>
>>>>   // Equivalent to: func clone() -> GenericBox<Contents>
>>>>   func clone() -> GenericBox {
>>>>     return GenericBox(contents: contents)
>>>>   }
>>>> }
>>>> extension GenericBox {
>>>>   func print() {
>>>>     // Equivalent to: let cloned: GenericBox<Contents>
>>>>     let cloned: GenericBox = clone()
>>>>     print(cloned.contents)
>>>>   }
>>>> }
>>>>
>>>>
>>>>    -
>>>>
>>>>    If the type is referenced from an unrelated scope, we attempt to
>>>>    infer the generic parameters.
>>>>
>>>>    For example,
>>>>
>>>> func makeABox() -> GenericBox<Int> {
>>>>   // Equivalent to: GenericBox<Int>(contents: 123)
>>>>   return GenericBox(contents: 123)
>>>> }
>>>>
>>>> The problem appears when the user expects the second behavior, but
>>>> instead encounters the first. For example, the following does not type
>>>> check:
>>>>
>>>> extension GenericBox {
>>>>
>>>>   func transform<T>(f: Contents -> T) -> GenericBox<T> {
>>>>     // We resolve 'GenericBox' as 'GenericBox<Contents>', rather than
>>>>     // inferring the type parameter
>>>>     return GenericBox(contents: f(contents))
>>>>   }
>>>> }
>>>>
>>>>
>>>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#proposed-solution>Proposed
>>>> solution
>>>>
>>>> The proposed solution is to remove the first rule altogether. If the
>>>> generic parameters cannot be inferred from context, they must be specified
>>>> explicitly with the usual Type<Args...> syntax.
>>>>
>>>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#detailed-design>Detailed
>>>> design
>>>>
>>>> This really just involves removing an existing piece of logic from the
>>>> type resolver code.
>>>>
>>>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#impact-on-existing-code>Impact
>>>> on existing code
>>>>
>>>> This will have a small impact on existing code that uses a pattern
>>>> similar to the above.
>>>>
>>>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#alternatives-considered>Alternatives
>>>> considered
>>>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#status-quo>Status
>>>> quo
>>>>
>>>> We could keep the current behavior, but one can argue it is not very
>>>> useful, and adds a special case where one is not needed.
>>>>
>>>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#more-complex-inference-of-generic-parameters>More
>>>> complex inference of generic parameters
>>>> We could attempt to unify the two rules for resolving a reference to a
>>>> generic type with no arguments, however this presents theoretical
>>>> difficulties with our constraint solver design. Even if it were easy to
>>>> implement, it would increase type checking type by creating new
>>>> possibilities to consider, with very little actual benefit.
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>
>>>
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160623/4ed66a3a/attachment.html>


More information about the swift-evolution mailing list