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

Slava Pestov spestov at apple.com
Thu Jun 23 16:00:38 CDT 2016


> On Jun 23, 2016, at 1:48 PM, Sean Heber <sean at fifthace.com> wrote:
> 
> So the only real downside of this is that if you don’t refer/use all of the generic types in this sort of situation, then it couldn’t figure it out? So the following wouldn’t be a problem even if rule 1 was eliminated because this actually ties other.value to self’s value and implies that other must be GenericBox<Contents>?
> 
> struct GenericBox<Contents: AnyObject> {
>    let value: Contents
> 
>    func test(other: GenericBox) -> Bool {
>        return value === other.value
>    }
> }
> 
> I might be totally not understanding, though. :P

This would *not* work with my proposed change. Even though we could theoretically infer that the parameter must be a GenericBox<Contents> to make the === type check, in practice Swift’s type checker operates at the expression level.

Global type inference is not something we’re considering, because of the compile-time cost, increased difficulty in producing localized diagnostics, and the loss of too much explicit type information.

> 
> l8r
> Sean
> 
> 
>> On Jun 23, 2016, at 3:30 PM, Slava Pestov via swift-evolution <swift-evolution at swift.org> 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
>>> 	• Author: Slava Pestov
>>> 	• Status: Awaiting review
>>> 	• Review manager: TBD
>>> 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
>>> 
>>> 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))
>>>  }
>>> }
>>> 
>>> 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.
>>> 
>>> Detailed design
>>> 
>>> This really just involves removing an existing piece of logic from the type resolver code.
>>> 
>>> Impact on existing code
>>> 
>>> This will have a small impact on existing code that uses a pattern similar to the above.
>>> 
>>> Alternatives considered
>>> 
>>> 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.
>>> 
>>> 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
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 



More information about the swift-evolution mailing list