The Generics Manifesto and single-element tuples

I didn't say that the lack of unlabeled 1-tuples is the cause, I said that the underlying problem is

I've been bumping into and reporting tuple- and parentheses related bugs since the first versions of Swift, and its not just me. Here is a recent bug that @mattrips reported and just started working on, it has some interesting comments.

Also, the following is another example of the confusion caused by 1-tuples having the same type as their element:

But the language reference says that 1-tuple types don't exist:

All tuple types contain two or more types, except for Void which is a type alias for the empty tuple type, ().

It also says:

In Swift, there are two kinds of types: named types and compound types. A named type is a type that can be given a particular name when it’s defined. Named types include classes, structures, enumerations, and protocols.
/.../
A compound type is a type without a name, defined in the Swift language itself. There are two compound types: function types and tuple types.
/.../
You can put parentheses around a named type or a compound type. However, adding parentheses around a type doesn’t have any effect. For example, (Int) is equivalent to Int.

I would interpret this as 1-tuples not being a thing, they don't exist, in any way. And (Int) == Int is a "named type", not a tuple type.

But if, as you say, 1-tuples do exist, and are equivalent to their element's type, because (T) == T, then all "named and compound types" are "compound types", which sounds strange.

I'm afraid I'm still no wiser than when I wrote:


I'd like to see a code example illustrating the following:

Because as far as I can see, the opposite is true: Special casing 1-tuples spreads through all things dealing with / affected by 1-tuples, as eg variadic functions in their unary form. Here is an example of a user who is annoyed by the special casing of 1-tuples.

I wish Swift could have more consistent (ie fewer and simpler) rules in this area. And the only reason I can see for why tuples can't simply have zero or more elements and why the same rules can't apply to all tuple types, is the conflation-of-parentheses-syntax-issue, without which I doubt anyone would find it natural to consider the type of a single element tuple equivalent to the type of its element.

I'd still say that the current rules are complex and confusing (for both users and compiler devs):

  • Tuple types can have 0, not 1, or 2 or more elements, but it seems like 1-tuples also exist, in some way.

  • It seems like all types are tuple types (because (T) is equivalent to T) but I'm not sure.

  • To me, saying that there exist single element tuples and that their type is equivalent to the type of their (single) element, and that the language prevents us from naming or accessing their single element or otherwise treating them like all other tuple types, sounds almost as strange as if for example enum MyEnum { case singleCase(String) } would not be allowed because it has just a single case, although single-case enums would still exist, in a way, and their type would always be equivalent to the type of the associated value of their single case (provided it has an associated value of course). Or, if Swift had fixed size array types, with a type level count, if single element fixed size arrays would be considered unnecessary and therefore although they would kind of exist, their type would be equivalent to their single element's type, and we would not be allowed to access its single element in the same way as we access all other fixed size array types (of sizes 0 or 2 or more).

  • There has always been and still are lots of tuple- and parentheses- related compiler bugs. My feeling is that I'm no longer sure whether reporting and "fixing" these bugs simplifies or complicates the situation.

2 Likes