- Proposal: SE-0110
- Authors: Vladimir S., Austin Zheng
- Status: Accepted (Rationale)
- Review manager: Chris Lattner
Swift's type system should properly distinguish between functions that take one tuple argument, and functions that take multiple arguments.
Discussion: pre-proposal
Right now, the following is possible:
let fn1 : (Int, Int) -> Void = { x in
// The type of x is the tuple (Int, Int).
// ...
}
let fn2 : (Int, Int) -> Void = { x, y in
// The type of x is Int, the type of y is Int.
// ...
}
A variable of function type where there exist n parameters (where n > 1) can be assigned a value (whether it be a named function, a closure literal, or other acceptable value) which either takes in n parameters, or one tuple containing n elements. This seems to be an artifact of the tuple splat behavior removed in SE-0029.
The current behavior violates the principle of least surprise and weakens type safety, and should be changed.
We propose that this behavior should be fixed in the following ways:
-
A function type declared with n parameters (n > 1) can only be satisfied by a function value which takes in n parameters. In the above example, only the
fn2
expression would be considered valid. -
To declare a function type with one tuple parameter containing n elements (where n > 1), the function type's argument list must be enclosed by double parentheses:
let a : ((Int, Int, Int)) -> Int = { x in return x.0 + x.1 + x.2 }
We understand that this may be a departure from the current convention that a set of parentheses enclosing a single object are considered semantically meaningless, but it is the most natural way to differentiate between the two situations described above and would be a clearly-delineated one-time-only exception.
Minor changes to user code may be required if this proposal is accepted.
Don't make this change.