Update “tuple” handling – Alternative “2-way” version of #1560#1608
Update “tuple” handling – Alternative “2-way” version of #1560#1608Nigel-Ecma wants to merge 1 commit intodotnet:draft-v8from
Conversation
This replaces the 3-way division of tuples & deconstructing; into *tuple_literal*, *deconstructing_assignment* and *local_deconstructing_declaration*; with a 2-way division; into *tuple_literal* and *deconstructing_assignment*. The distinction between deconstruction assigning to *existing* vs. *new* variables is not syntactical in this version, even though C# distinguishes the two cases. Instead a textual list of restrictions is provided which govern what a *deconstructor* can contain based on its position within the code. Other changes since dotnet#1560 include: - Renamed abridged_* rules per suggestion. - Inclusion of *declaration_expression* as an option in a *for_initializer* (this was an accidental omission in dotnet#1560). This topic is not yet complete: deconstructing foreach, which was missing in v7, is not yet included. This will either be added in an update to this PR, or as a new PR building on this one.
BillWagner
left a comment
There was a problem hiding this comment.
This is great @Nigel-Ecma
I had a few small questions / nits in text to consider. One may even be just the result of my failing eyesight.
|
|
||
| #### §tuple-runtime-representation Runtime representation | ||
|
|
||
| > *Note*: Unlike other types such as arrays, the runtime representation of tuple types is specified in terms of a set of generic value types, and a tuple may be directly referenced in terms of this representation. However the runtime representation of these generic value types remains implementation defined. *end note* |
There was a problem hiding this comment.
I'm not sure what this note is conveying. We've said (normatively) that a tuple's runtime representation is System.ValueTuple<...>. What is "implementation defined" about that?
| The result of the deconstruction is the *tuple-literal* formed from the values returned via the out parameters of a call to `E.Deconstruct(...)`. The result is semantically equivalent to replacing `E` with the following pseudo-code: | ||
|
|
||
| >```csharp | ||
| > E.Deconstruct(out T1 v1, ..., out TN vn) andThen (v1, ..., vn); | ||
| >``` | ||
|
|
||
| Where `andThen` is a pseudo C# operation which performs its left-hand operand and then returns its right-operand as the result. | ||
| <!-- markdownlint-disable MD028 --> | ||
|
|
||
| <!-- markdownlint-enable MD028 --> | ||
| >> *Note*: `andThen` is the equivalent of C & C++’s comma operator. *end note* |
There was a problem hiding this comment.
I think we want all these lines to be indented, as they are part of the bullet item on 1272. (I apologize if they already are, that's just hard are to see.
| > *Note*: ANTLR grammar semantics enforce this requirement due to the ordering of the alternatives. *Semantically* there is no overlap between the four alternatives, this is a syntactic disambiguation. | ||
|
|
||
| The `+=` and `-=` operators with an event access expression as the left operand are called the ***event assignment operator***s. No other assignment operator is valid with an event access as the left operand. The event assignment operators are described in [§12.23.5](expressions.md#12235-event-assignment). | ||
| The *simple_assignment* and *compound_assignment* expressions assign a new value to a variable, a property, or an indexer element. Event assignment ([§12.23.5](expressions.md#12235-event-assignment)), a subset of *compound_assignment*, assigns a new value to an event. The *ref_assignment* expression assigns a variable reference ([§9.5](variables.md#95-variable-references)) to a reference variable ([§9.7](variables.md#97-reference-variables-and-returns)). The *deconstructing_assignment* assigns new values to one or more *variable_reference*s. |
There was a problem hiding this comment.
nit: Would deconstructing_assignment require "two or more variable_references?
| ### 12.23.4 Compound assignment | ||
|
|
||
| If the left operand of a compound assignment is of the form `E.P` or `E[Ei]` where `E` has the compile-time type `dynamic`, then the assignment is dynamically bound ([§12.3.3](expressions.md#1233-dynamic-binding)). In this case, the compile-time type of the assignment expression is `dynamic`, and the resolution described below will take place at run-time based on the run-time type of `E`. If the left operand is of the form `E[Ei]` where at least one element of `Ei` has the compile-time type `dynamic`, and the compile-time type of `E` is not an array, the resulting indexer access is dynamically bound, but with limited compile-time checking ([§12.6.5](expressions.md#1265-compile-time-checking-of-dynamic-member-invocation)). | ||
| ```ANTLR |
There was a problem hiding this comment.
Everything here is correct, but I'm wondering why this is shown as an addition. I'm curious where it was moved from?
Fixes: #1155
Replaces: PR #1366, #1538, #1570
Alternative to: #1560
This replaces #PR1560’s 3-way division of tuples & deconstruction; into tuple_literal, deconstructing_assignment and local_deconstructing_declaration; with a 2-way division; into tuple_literal and deconstructing_assignment.
The distinction between a deconstruction assigning to existing vs. new variables is not syntactic in this version. Instead a textual list of restrictions is specified which; by governing what a deconstructor can contain based on its position within the code; distinguish the two cases.
Other changes since PR1560 include:
This topic is not yet complete: The deconstructing foreach stattement, which was missing in v7, is not yet included. This will either be added in an update to this PR, or as a new PR building on this one. For this reason this PR is marked as draft.