Skip to content

Commit

Permalink
Deconstruction into dynamic array and dynamic indexer
Browse files Browse the repository at this point in the history
  • Loading branch information
jcouv committed Sep 10, 2016
1 parent 32a8f40 commit c994d12
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,20 @@ private void ApplyAssignments(BoundDeconstructionAssignmentOperator node, ArrayB
var assignmentInfo = node.AssignmentSteps[i];
AddPlaceholderReplacement(assignmentInfo.OutputPlaceholder, lhsTargets[i]);

// All the input placeholders for the assignments should already be set
var assignment = VisitExpression(assignmentInfo.Assignment);
var assignment = assignmentInfo.Assignment;

// All the input placeholders for the assignments should already be set with lowered nodes
Debug.Assert(assignment.Left.Kind == BoundKind.DeconstructValuePlaceholder);
Debug.Assert(assignment.Right.Kind == BoundKind.DeconstructValuePlaceholder);
var rewrittenLeft = (BoundExpression)Visit(assignment.Left);
var rewrittenRight = (BoundExpression)Visit(assignment.Right);

var loweredAssignment = MakeAssignmentOperator(assignment.Syntax, rewrittenLeft, rewrittenRight, assignment.Type,
used: true, isChecked: false, isCompoundAssignment: false);

RemovePlaceholderReplacement(assignmentInfo.OutputPlaceholder);

stores.Add(assignment);
stores.Add(loweredAssignment);
}
}

Expand Down Expand Up @@ -150,7 +158,7 @@ private ImmutableArray<BoundExpression> LeftHandSideSideEffects(ImmutableArray<B

foreach (var variable in variables)
{
lhsReceivers.Add(TransformCompoundAssignmentLHS(variable, stores, temps, isDynamicAssignment: false));
lhsReceivers.Add(TransformCompoundAssignmentLHS(variable, stores, temps, isDynamicAssignment: variable.Type.IsDynamic()));
}

return lhsReceivers.ToImmutableAndFree();
Expand Down
151 changes: 151 additions & 0 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3044,5 +3044,156 @@ static void Main()
var comp = CompileAndVerify(source, expectedOutput: "0 10 ", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics();
}

[Fact]
public void TupleDeconstructionIntoDynamicArrayIndexer()
{
string source = @"
class C
{
static void Main()
{
dynamic x = new string[] { """", """" };
M(x);
System.Console.WriteLine($""{x[0]} {x[1]}"");
}
static void M(dynamic x)
{
(x[0], x[1]) = (""hello"", ""world"");
}
}
";
var comp = CompileAndVerify(source, expectedOutput: "hello world", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef, CSharpRef, SystemCoreRef });
comp.VerifyDiagnostics();
}

[Fact]
public void IntTupleDeconstructionIntoDynamicArrayIndexer()
{
string source = @"
class C
{
static void Main()
{
dynamic x = new int[] { 1, 2 };
M(x);
System.Console.WriteLine($""{x[0]} {x[1]}"");
}
static void M(dynamic x)
{
(x[0], x[1]) = (3, 4);
}
}
";
var comp = CompileAndVerify(source, expectedOutput: "3 4", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef, CSharpRef, SystemCoreRef });
comp.VerifyDiagnostics();
}

[Fact]
public void DeconstructionIntoDynamicArrayIndexer()
{
string source = @"
class C
{
static void Main()
{
dynamic x = new string[] { """", """" };
M(x);
System.Console.WriteLine($""{x[0]} {x[1]}"");
}
static void M(dynamic x)
{
(x[0], x[1]) = new C();
}
public void Deconstruct(out string a, out string b)
{
a = ""hello"";
b = ""world"";
}
}
";
var comp = CompileAndVerify(source, expectedOutput: "hello world", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef, CSharpRef, SystemCoreRef });
comp.VerifyDiagnostics();
}

[Fact]
public void TupleDeconstructionIntoDynamicArray()
{
string source = @"
class C
{
static void Main()
{
dynamic[] x = new string[] { """", """" };
M(x);
System.Console.WriteLine($""{x[0]} {x[1]}"");
}
static void M(dynamic[] x)
{
(x[0], x[1]) = (""hello"", ""world"");
}
}
";
var comp = CompileAndVerify(source, expectedOutput: "hello world", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef, CSharpRef, SystemCoreRef });
comp.VerifyDiagnostics();
}

[Fact]
public void DeconstructionIntoDynamicArray()
{
string source = @"
class C
{
static void Main()
{
dynamic[] x = new string[] { """", """" };
M(x);
System.Console.WriteLine($""{x[0]} {x[1]}"");
}
static void M(dynamic[] x)
{
(x[0], x[1]) = new C();
}
public void Deconstruct(out string a, out string b)
{
a = ""hello"";
b = ""world"";
}
}
";
var comp = CompileAndVerify(source, expectedOutput: "hello world", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef, CSharpRef, SystemCoreRef });
comp.VerifyDiagnostics();
}

[Fact]
public void DeconstructionIntoDynamicMember()
{
string source = @"
class C
{
static void Main()
{
dynamic x = System.ValueTuple.Create(1, 2);
(x.Item1, x.Item2) = new C();
System.Console.WriteLine($""{x.Item1} {x.Item2}"");
}
public void Deconstruct(out int a, out int b)
{
a = 3;
b = 4;
}
}
";
var comp = CompileAndVerify(source, expectedOutput: "3 4", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef, CSharpRef, SystemCoreRef });
comp.VerifyDiagnostics();
}
}
}
20 changes: 20 additions & 0 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDynamicTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13966,6 +13966,26 @@ .maxstack 12
");
}

[Fact]
public void CompoundAssignment()
{
string source = @"
class C
{
static void Main()
{
dynamic[] x = new string[] { ""hello"" };
x[0] += ""!"";
System.Console.Write(x[0]);
}
}
";
var comp = CompileAndVerify(source, expectedOutput: "hello!", additionalRefs: new[] { ValueTupleRef, SystemRuntimeFacadeRef, CSharpRef, SystemCoreRef });
comp.VerifyDiagnostics();
// No runtime failure (System.ArrayTypeMismatchException: Attempted to access an element as a type incompatible with the array.)
// because of the special handling for dynamic in LocalRewriter.TransformCompoundAssignmentLHS
}

#endregion

#region Object And Collection Initializers
Expand Down

0 comments on commit c994d12

Please sign in to comment.