Skip to content
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

Merged
merged 10 commits into from
May 24, 2016
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Updating doc
  • Loading branch information
jcouv committed May 20, 2016
commit e046522c6e92feb2a4b8149b6a3ce9045d560a8e
43 changes: 14 additions & 29 deletions docs/features/deconstruction.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Copy link
Member

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?

Copy link
Member Author

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.

```

**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.

Copy link
Member

Choose a reason for hiding this comment

The 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)

Copy link
Member Author

Choose a reason for hiding this comment

The 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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made some update the the deconstruction.md which reflect latest LDM, but are ahead of the implementation at this point.

- 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):

Expand Down Expand Up @@ -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**

Expand Down