+1 again.  Thanks for ferreting out these surprising behaviors Slava!

I did not realize the shorthand you propose to remove was possible (is this 
documented anywhere?).  On the other hand, I make use of the inference that 
does not work correctly in the “broken” example all the time.  

This is another one that would have been pretty confusing to me had I run into 
it.  I don’t believe there is any other context where explicit type arguments 
are required in a type context where they should be inferred.  Fixing this is 
really important.

I think a reasonably strong argument can be made to remove the first behavior 
even without this conflict.  I really like Swift’s approach of making type 
information explicit in signatures.  Allowing it to be inferred in an obscure 
corner case violates that principle.  

I also think it is reasonable to require the programmer to state all type 
information explicitly when it isn’t inferred.  This makes the code more clear 
to a reader.  Type information is either stated or not stated, never partially 
stated (requiring the programmer to remember what pieces are inferred as well 
as when partial inference is possible and when it is not possible).

It’s also worth noting that in one of your clone example the whole type could 
be inferred:

let cloned = clone()


> On Jun 23, 2016, at 3:14 PM, Slava Pestov via swift-evolution 
> <[email protected]> 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
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to