[swift-evolution] The state and the future of function types in Swift 4

Vladimir.S svabox at gmail.com
Wed Jun 14 17:29:32 CDT 2017

I do understand that core team is very busy, but I hope they'll find a minute to 
reply in couple of words to this message. Even "we are still thinking about this" 
would be great. Of course any other's opinion is also very welcome.

I think we all need some clarification about function types in Swift 4, especially in 
light of recent hot discussion of reverting of SE-0110, which raised a couple of 
questions that IMO should be answered before Swift 4 is released or is in final 
stage, and I can't see any clear answer from core team regarding the subject.
(If I missed something - sorry, please point me)

The main question I have : Will *type* of function taking a list of arguments be the 
same as type of function taking one tuple argument?
Then, what code can prove/show that these *types* are different and not the same ?

Answers to these question can show what situation we'll have with function types in 
Swift 4 and for very long period after Swift 4.
Seems like strange question as we know obvious answer, but as I understand, the 
answer is not so obvious.

As I understand, if we'll still have
'type(of: funcOfOneTuple) == type(of: funcOfArgList)' == true
(as we have even in current snapshot of Swift 4) - we are going to have broken type 
system for function types for very long time(when we'll be allowed for source 
breaking changes after Swift 4?)

I was told that Swift can have some bugs in this area currently and after Swift 4 
release, but don't worry, they'll be just fixed in some point of time after Swift 4.
But I insist, we are not talking about _bugs_, but about allowed syntax and code 
behavior, that can't be 'just' fixed without breaking some sources(and again probably 
in places where was not expected). Also, it's weird that these long-running "bugs" 
will still exists in Swift 4(and so, for long period after it) while SE-0066 and 
SE-0110 was accepted to be implemented in *Swift 3*.

I'll try to illustrate what I mean and why asking exactly that question.

	func fooParam(_ x: Int, _ y: Int){}
	func fooTuple(_ x: (Int, Int)) {}

	func fooEmpty() {}
	func fooVoid(_: Void) {}

currently, in Swift 4 snapshot we have this:

* type(of: fooTuple)  				// (Int,Int)->()
* type(of:fooParam) == type(of:fooTuple) 	// true
* fooParam is ((Int,Int))->()			// true
* fooTuple is (Int,Int)->() 			// true

* let foo : (Int,Int)->() = fooTuple
   foo(1,2)					// fooTuple called with 2 arguments

* let bar : ((Int,Int))->() = fooParam
   bar((1,2))					// fooParam called with 1 tuple arg

* type(of: fooEmpty) == type(of: fooVoid)	// true
* fooVoid is ()->()				// true
* fooEmpty is (_: Void)->()			// true

* let foo : ()->() = fooVoid
   foo()						// fooVoid called with no () arg

* let bar : (_: Void)->() = fooEmpty
   bar(())					// fooEmpty called with () arg sent

While in some cases you can't use fooParam where fooTuple is expected, but seems like 
underlying type of each is the same, so in other cases you can and this _will_ be 
used in code and can't be "fixed" without breaking some sources.

Also, this raises a question : if the type is the same, why we can't freely use 
closure of type fooParam if fooTuple is expected. And how SE-0066 and SE-0110 in this 
case could be considered as fully implemented in Swift 4.

So, I'd really appreciate some clarifications/plans/thoughts/opinions about this.

Thank you for attention,

More information about the swift-evolution mailing list