csharpstandard icon indicating copy to clipboard operation
csharpstandard copied to clipboard

Tuple conversion are incorrectly specified

Open 333fred opened this issue 1 year ago • 2 comments

Describe the bug

The compiler implements both a tuple type conversion, and a tuple literal conversion from expression. The spec currently only covers that latter conversion. As a concrete example of a feature that explicitly designed for and allowed, but the spec says is illegal:

short s = 1;

(int, int) t1 = (s, s); // As said in the spec, this is a tuple expression conversion
(short, short) t2 = (s, s);
(int, int) t3 = t2; // By the spec, there shouldn't be a conversion here, but the compiler allows a tuple type conversion from (short, short) to (int, int)

Specifically, https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/conversions.md#10213-implicit-tuple-conversions is the only conversions portion of the specification that touches tuples, and it covers tuple expressions. These are defined by https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#1286-tuple-expressions. In t3 = t2, t2 is not a tuple expression, but is instead a simple name: https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#1284-simple-names; since we're not dealing tuple expressions, implicit tuple conversions don't apply, and the spec says that no conversion should exist from t2 to t3.

333fred avatar Aug 12 '24 17:08 333fred

Oops…

I suggest this error has crept in due to the melding of tuple construction and tuple conversion into a single operation – the implicit tuple conversion §10.2.13.

Possible fix:

  • In §12.8.6 Tuple expressions define a tuple value in terms of ValueTuple and not by referencing tuple conversion.
  • In §12.2.2 Values of expressions change the fourth bullet to reference §12.8.6 and not tuple conversion. Also while in this clause fix the issue that when the fourth bullet was added it wasn't included in the final sentence of the preceding paragraph which still only mentions three things.
  • §10.2.13 Implicit tuple conversions can then start “An implicit conversion exists from an expression E with a tuple type S to a tuple type T if S has the same arity as T and an implicit conversion exists from each element type in S to the corresponding element type in T.” The ValueTuple stuff then gets removed as it is now in §12.8.6.

A possible criticism of this approach is that it might define/imply (depending on wording) something like (var a, var b) = (42, 24); as creating a ValueTuple and then destroying it – but what if it does? Not doing so is a compiler optimisation surely? However if wished the Standard could make it clear that eliding temporary ValueTuples is valid, though I suspect eliding temporaries is always valid.

Nigel-Ecma avatar Aug 12 '24 20:08 Nigel-Ecma

A possible criticism of this approach is that it might define/imply (depending on wording) something like (var a, var b) = (42, 24); as creating a ValueTuple and then destroying it – but what if it does?

FWIW, I've always viewed this operation as doing exactly that, and the compiler optimized to avoid creating the tuple. We use that exact wording when talking about expression-bodied constructors that do something like MyClass(int a, b) => (this.a, this.b) = (a, b);

333fred avatar Aug 12 '24 21:08 333fred

Bill will have a look.

jskeet avatar Jun 11 '25 20:06 jskeet

Reopened as it wasn't actually fixed.

jskeet avatar Oct 22 '25 20:10 jskeet

This issue has revealed some more issues with the specification of tuples. They all need to be resolved for v8…

Nigel-Ecma avatar Nov 17 '25 02:11 Nigel-Ecma