On tuple syntax and parentheses

This discussion from Sum-tuples popped into my head over a more recent discussion with the problems of regular tuples, general syntax that uses parentheses, and single-element tuples.

The problem: tuples were overloaded for everything; all multi-element entities were supposed to be secretly implemented by tuples. That's why function parameter syntax was so chummy with tuples. Heck, ABI-level function passing explodes tuples, since tuples and function parameter packs weren't distinct. Now they are, but we still have the damage that a single-item tuple is a pain to use/interpret.

In the sum-tuple thread, anonymous sum tuples were expressed by a slightly different syntax for the standard tuples:

typealias RegularSumTuple = (| TypeWithOptionalLablel1, TypeWithOptionalLabel2, ... |)
typealias TypeCollaspedSumTuple = (< Type1, Type2, ... >)
typealias UncheckedSumTuple = @unsafe(< Type1, Type2, ... >)

Now I'm wondering if we should add a fourth special parentheses group, for product-tuples (i.e. regular tuples):

typealias Void = (* *)
typealias SingleElementTuple = (* TypeWithOptionalLabel *)
typealias MultipleElementTuple = (* TypeWithOptionalLabel1, TypeWithOptionalLabel2, ... *)

This gives an unambiguous syntax for product tuples distinct from expression-grouping or function parameter parentheses. It also gives an unambiguous syntax for single-element product tuples.

But "(* *)" remind me of Pascal comments. Maybe "(& &)"?

Hmm, "&" can sometimes be used as a prefix (to inout variables), so that doesn't seem like a good idea.

Maybe "#(" and ")#"?

Hmm, another idea: since the items of a sum-tuple can't simultaneously be active, maybe using semicolons instead of commas could work.

product-tuple: (< item1 , item2 , ... >)
sum-tuple: (< item1 ; item2 ; ... >)
undiscriminated sum-tuple: @unsafe (< item1 ; item2 ; ... >)

For regular sum-tuples, mySumTuple as MyType for reading works if the current member has that type, even if there are multiple members with that type. You have to specify the specific member for writing.

Undiscriminated sum-tuples are like C unions. The individual items, if any, cannot have labels.

The empty product-tuple can be differentiated from the empty sum-tuple with an extraneous semicolon:

typealias Void = (< >)  // Should "(< , >)" be allowed too?
typealias Never = (< ; >)

We have to check if having "(<>)", where the tuple brackets abut without space, is OK for the lexer. And if "(<,>)" (if kept) and "(<;>)" are OK too.

Oh, I just realized that we can't tell if "(< someLabel: SomeType >)" is a single-element product-tuple or sum-tuple. But does that really matter; would they be implemented differently than just having a single SomeType object?