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: nested scenario #11715

Merged
merged 13 commits into from
Jun 7, 2016
Merged

Conversation

jcouv
Copy link
Member

@jcouv jcouv commented Jun 2, 2016

Adding support for nested deconstruction-assignments, such as (x, (y, z)) = M(); or (x, (y, z)) = (1, (2, 3));.

The bound node now contains:

  • all the LHS variables (flat list),
  • the expression on the right (used as target for deconstruction),
  • a list of deconstruction steps (which has a deconstruction method and placeholders for input and outputs, with the method being null in tuple cases),
  • and a list of assignment steps.

Note conversions are still coupled with assignments, but I have a work item (in #11299) to do all conversions first then all assignments.

CC @dotnet/roslyn-compiler for review.

Error(diagnostics, ErrorCode.ERR_DeconstructRequiresExpression, node);
return BadExpression(node, checkedVariables.Concat(boundRHS).ToArray());
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Can this if be moved before try/finally and deconstructionSteps declaration?

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, indeed. Thanks

<Field Name="AssignmentSteps" Type="ImmutableArray&lt;BoundDeconstructionAssignmentOperator.AssignmentStep&gt;" Null="NotApplicable" SkipInVisitor="true"/>
</Node>

<Node Name="BoundDeconstructionVariables" Base="BoundExpression">
Copy link
Member

Choose a reason for hiding this comment

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

Why a BoundExpression rather than BoundNode?

Copy link
Member Author

Choose a reason for hiding this comment

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

So, this bound node is never output from binding at all. But during binding, I have bound expressions for the LHS, which need to be organized in a tree.
Because all simple variables are BoundExpression, it is convenient that this is also BoundExpression (rather than BoundNode). But I'm open to suggestions.
I agree that having a bound node that never escapes binding is strange.

Copy link
Member

Choose a reason for hiding this comment

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

Where do we use checkedVariables as (array of) BoundExpression rather than BoundNode? Or is it more than just checkedVariables that is the concern?

DiagnosticBag bag = new DiagnosticBag();
MethodSymbol deconstructMethod = FindDeconstruct(checkedVariables, boundRHS, node, bag);
var bag = DiagnosticBag.GetInstance();
MethodSymbol deconstructMethod = FindDeconstruct(variables.Length, targetPlaceholder, syntax, bag);
if (!diagnostics.HasAnyErrors())
Copy link
Member

Choose a reason for hiding this comment

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

Is bag only added if diagnostics is empty to avoid cascading errors? Are we sure existing diagnostics are from the same expression (in other words, are we sure bag contains errors related to those in diagnostics)? Perhaps add bag always.

/// </summary>
static private DeconstructStep MakeNonTupleDeconstructStep(
BoundDeconstructValuePlaceholder targetPlaceholder,
AssignmentExpressionSyntax syntax,
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment about associated syntax node.

@AlekseyTs
Copy link
Contributor

Done with the review pass

@jcouv
Copy link
Member Author

jcouv commented Jun 4, 2016

Pushed some commits addressing the feedback.
I'm on the fence about removing BoundDeconstructionVariables as it would make it easier to track portions of syntax on the LHS.

@AlekseyTs
Copy link
Contributor

Having BoundDeconstructionVariables as a helper node seems fine as long as it doesn't survive initial binding. It does provide an easy way to track relevant syntax node. Otherwise we would have to use a tuple for this.


In reply to: 223733070 [](ancestors = 223733070)

private class DeconstructionVariable
{
public BoundExpression Single;
public ImmutableArray<DeconstructionVariable>? Nested;
Copy link
Member

Choose a reason for hiding this comment

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

Consider using non-nullable ImmutableArray<DeconstructionVariable> where the unset value is default(Immutable<DeconstructionVariable>).

Copy link
Member

@VSadov VSadov Jun 6, 2016

Choose a reason for hiding this comment

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

There is a type loader bug that would cause a struct S1 containing ImmutableArray< S1 > be rejected as having a layout cycle (there is not real cycle though since IA wraps a ref array)
CLR knows about this bug, but it is too risky area to fix right now.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

@jcouv
Copy link
Member Author

jcouv commented Jun 6, 2016

@AlekseyTs @cston I pushed a change that uses default instead of a nullable and avoids IEnumerable.
The tracking of more precise locations is deferred to a follow-up work item.

@jcouv
Copy link
Member Author

jcouv commented Jun 6, 2016

@AlekseyTs @cston Please let me know if ok to merge. Thanks

TypeSymbol lhsAsTuple = TupleTypeSymbol.Create(locationOpt: null, elementTypes: lhsTypes, elementLocations: default(ImmutableArray<Location>), elementNames: default(ImmutableArray<string>), compilation: Compilation, diagnostics: diagnostics);
var typedRHS = GenerateConversionForAssignment(lhsAsTuple, boundRHS, diagnostics);
public BoundExpression Single;
public ImmutableArray<DeconstructionVariable> Nested;
Copy link
Member

Choose a reason for hiding this comment

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

readonly for both fields.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

@cston
Copy link
Member

cston commented Jun 6, 2016

LGTM

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Jun 7, 2016

LGTM, modulo the fact that lhsTemps are still not renamed to lhsTargets in LocalRewriter.

@jcouv jcouv merged commit 326f70b into dotnet:features/tuples Jun 7, 2016
@jcouv jcouv deleted the nesting branch June 7, 2016 19:02
@jcouv
Copy link
Member Author

jcouv commented Jun 7, 2016

Merged. Thanks for the review and feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants