-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deconstruction-assignment for tuples #11457
Changes from 1 commit
6967473
dcb9c69
a2c290b
4f443f0
e046522
7170bd2
227c3a5
1688f5f
66662a3
c7b60a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,17 +36,18 @@ In short, what this does is find a `Deconstruct` method on the expression on the | |
The existing assignment binding currently checks if the variable on its left-hand-side can be assigned to and if the two sides are compatible. | ||
It will be updated to support deconstruction-assignment, ie. when the left-hand-side is a tuple-literal/tuple-expression: | ||
|
||
- Each item on the left needs to be assignable and needs to be compatible with corresponding position on the right | ||
- Needs to break the right-hand-side into items. That step is un-necessary if the right-hand-side is already a tuple though. | ||
- Each item on the left needs to be assignable and needs to be compatible with corresponding position on the right (resulting from previous step). | ||
- Needs to handle nesting case such as `(x, (y, z)) = M();`, but note that the second item in the top-level group has no discernable type. | ||
|
||
The lowering for deconstruction-assignment would translate: `(expressionX, expressionY, expressionZ) = (expressionA, expressionB, expressionC)` into: | ||
In the general case, the lowering for deconstruction-assignment would translate: `(expressionX, expressionY, expressionZ) = expressionRight` into: | ||
|
||
``` | ||
tempX = &evaluate expressionX | ||
tempY = &evaluate expressionY | ||
tempZ = &evaluate expressionZ | ||
|
||
tempRight = evaluate right and evaluate Deconstruct | ||
tempRight = evaluate right and evaluate Deconstruct in three parts | ||
|
||
tempX = tempRight.A (including conversions) | ||
tempY = tempRight.B (including conversions) | ||
|
@@ -80,23 +81,16 @@ evaluate side-effect on the left-hand-side variables | |
evaluate Deconstruct passing the references directly in | ||
``` | ||
|
||
Note that the feature is built around the `Deconstruct` mechanism for deconstructing types. | ||
`ValueTuple` and `System.Tuple` will rely on that same mechanism, except that the compiler may need to synthesize the proper `Deconstruct` methods. | ||
|
||
In the case where the expression on the right is a tuple, the evaluation order becomes: | ||
``` | ||
evaluate side-effect on the left-hand-side variables | ||
evaluate the right-hand-side and do a tuple conversion | ||
assign element-wise from the right to the left | ||
``` | ||
|
||
**Work items, open issues and assumptions to confirm with LDM:** | ||
Note that tuples (`System.ValueTuple`) don't need to invoke Deconstruct. | ||
But `System.Tuple` will rely on the Deconstruct mechanism. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per LDM, I believe System.Tuple will get special handling that does not depend on Deconstruct (i.e. for long System.Tuple types) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, my work items list tracks "System.Tuple deconstruction". I'll update the spec then. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've made some update the the |
||
- I assume this should work even if `System.ValueTuple` is not present. | ||
- How is the Deconstruct method resolved? | ||
- I assumed there can be no ambiguity. Only one `Deconstruct` is allowed (in nesting cases we have no type to guide the resolution process). | ||
- But we may allow a little bit of ambiguity and preferring an instance over extension method. | ||
- Do the names matter? `int x, y; (a: x, b: y) = M();` | ||
- Can we deconstruct into a single out variable? I assume no. | ||
- I assume no compound assignment `(x, y) += M();` | ||
- [ ] Provide more details on the semantic of deconstruction-assignment, both static (The LHS of the an assignment-expression used be a L-value, but now it can be L-value -- which uses existing rules -- or tuple_literal. The new rules for tuple_literal on the LHS...) and dynamic. | ||
- [ ] Discuss with Aleksey about "Deconstruct and flow analysis for nullable ref type" | ||
- [ ] Validate any target typing or type inference scenarios. | ||
- The deconstruction-assignment is treated separately from deconstruction-declaration, which means it doesn't allow combinations such as `int x; (x, int y) = M();`. | ||
|
||
###Deconstruction-declaration (deconstruction into new variables): | ||
|
||
|
@@ -158,20 +152,11 @@ constant_declarator // not sure | |
; | ||
``` | ||
|
||
Treat deconstruction of a tuple into new variables as a new kind of node (AssignmentExpression). | ||
Treat deconstruction of a tuple into new variables as a new kind of node (not AssignmentExpression). | ||
It would pick up the behavior of each contexts where new variables can be declared (TODO: need to list). For instance, in LINQ, new variables go into a transparent identifiers. | ||
It is seen as deconstructing into separate variables (we don't introduce transparent identifiers in contexts where they didn't exist previously). | ||
|
||
Should we allow this? | ||
`var t = (x: 1, y: 2); (x: var a, y: var b) = t;` | ||
or `var (x: a, y: b) = t;` | ||
(if not, tuple names aren't very useful?) | ||
|
||
- [ ] Add example: var (x, y) = | ||
- [ ] Semantic (cardinality should match, ordering including conversion, | ||
- [ ] What are the type rules? `(string s, int x) = (null, 3);` | ||
|
||
- Deconstruction for `System.ValueTuple`, `System.Tuple` and any other type involves a call to `Deconstruct`. | ||
Just like deconstruction-assignment, deconstruction-declaration does not need to invoke `Deconstruct` for tuple types. | ||
|
||
**References** | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tuple conversion to what type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I basically make a fake tuple type that looks like what is on the LHS. I'm not sure what is a good way to explain that in the spec though.