From 254835c038c340a4a581854586f03ed2691b1cd7 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Wed, 5 Jan 2022 17:00:47 -0800 Subject: [PATCH 1/2] SpillSequenceSpiller.Spill - ensure sequences under ref assignments are spilled. Fixes #58569. --- .../Portable/Lowering/SpillSequenceSpiller.cs | 21 +- .../Test/Emit/CodeGen/IndexAndRangeTests.cs | 183 ++++++++++++++++++ 2 files changed, 201 insertions(+), 3 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/SpillSequenceSpiller.cs b/src/Compilers/CSharp/Portable/Lowering/SpillSequenceSpiller.cs index c235cf371059b..86f9fc49a6cf3 100644 --- a/src/Compilers/CSharp/Portable/Lowering/SpillSequenceSpiller.cs +++ b/src/Compilers/CSharp/Portable/Lowering/SpillSequenceSpiller.cs @@ -311,11 +311,26 @@ private BoundExpression Spill( continue; case BoundKind.Sequence: - // neither the side-effects nor the value of the sequence contains await - // (otherwise it would be converted to a SpillSequenceBuilder). if (refKind != RefKind.None) { - return expression; + var sequence = (BoundSequence)expression; + + PromoteAndAddLocals(builder, sequence.Locals); + builder.AddExpressions(sequence.SideEffects); + expression = sequence.Value; + continue; + } + + goto default; + + case BoundKind.AssignmentOperator: + var assignment = (BoundAssignmentOperator)expression; + if (assignment.IsRef && + assignment is not { Left.Kind: BoundKind.Local, Right.Kind: BoundKind.ArrayAccess }) // Optimize for some known to be safe scenarios. + { + var left = Spill(builder, assignment.Left, RefKind.Ref); + var right = Spill(builder, assignment.Right, RefKind.Ref); + expression = assignment.Update(left, right, assignment.IsRef, assignment.Type); } goto default; diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs index 62f565161795d..59752013a5dc6 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs @@ -3582,5 +3582,188 @@ class C Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(10, 5) ); } + + [Fact] + public void PatternIndexArrayAndAwait_01() + { + var src = @" +class C +{ + static async System.Threading.Tasks.Task M1(int[] arr) + { + arr[^1] = await System.Threading.Tasks.Task.FromResult(0); + } + + static async System.Threading.Tasks.Task Main() + { + var arr = new[] { 123 }; + System.Console.WriteLine(arr[0]); + await M1(arr); + System.Console.WriteLine(arr[0]); + } +} +"; + CompileAndVerifyWithIndexAndRange(src, expectedOutput: +@" +123 +0 +").VerifyDiagnostics(); + } + + [Fact] + public void PatternIndexArrayAndAwait_02() + { + var src = @" +class C +{ + static async System.Threading.Tasks.Task M1(int[] arr) + { + (arr[^1], arr[0]) = (123, await System.Threading.Tasks.Task.FromResult(124)); + } + + static async System.Threading.Tasks.Task Main() + { + var arr = new int[2]; + await M1(arr); + System.Console.WriteLine(arr[0]); + System.Console.WriteLine(arr[1]); + } +} +"; + CompileAndVerifyWithIndexAndRange(src, expectedOutput: +@" +124 +123 +").VerifyDiagnostics(); + } + + [Fact] + public void PatternIndexArrayAndAwait_03() + { + var src = @" +class C +{ + static async System.Threading.Tasks.Task M1((int x, int y)[] arr) + { + arr[^1].x = await System.Threading.Tasks.Task.FromResult(124); + } + + static async System.Threading.Tasks.Task Main() + { + var arr = new (int x, int y)[1]; + await M1(arr); + System.Console.WriteLine(arr[0].x); + } +} +"; + CompileAndVerifyWithIndexAndRange(src, expectedOutput: +@" +124 +").VerifyDiagnostics(); + } + + [Fact] + [WorkItem(58569, "https://github.com/dotnet/roslyn/issues/58569")] + public void PatternIndexArrayAndAwait_04() + { + var src = @" +class C +{ + static async System.Threading.Tasks.Task M1((int x, int y)[] arr) + { + (arr[^1].x, arr[0].y) = (123, await System.Threading.Tasks.Task.FromResult(124)); + } + + static async System.Threading.Tasks.Task Main() + { + var arr = new (int x, int y)[2]; + await M1(arr); + System.Console.WriteLine(arr[0].y); + System.Console.WriteLine(arr[1].x); + } +} +"; + CompileAndVerifyWithIndexAndRange(src, expectedOutput: +@" +124 +123 +").VerifyDiagnostics(); + } + + [Fact] + [WorkItem(58569, "https://github.com/dotnet/roslyn/issues/58569")] + public void PatternIndexArrayAndAwait_05() + { + var src = @" +class C +{ + static async System.Threading.Tasks.Task M1((int x, int y)[] arr) + { + arr[^1].x += await System.Threading.Tasks.Task.FromResult(124); + } + + static async System.Threading.Tasks.Task Main() + { + var arr = new (int x, int y)[] { (1, 2) }; + await M1(arr); + System.Console.WriteLine(arr[0].x); + } +} +"; + CompileAndVerifyWithIndexAndRange(src, expectedOutput: +@" +125 +").VerifyDiagnostics(); + } + + [Fact] + public void PatternIndexArrayAndAwait_06() + { + var src = @" +class C +{ + static async System.Threading.Tasks.Task M1(int[] arr) + { + arr[^1] += await System.Threading.Tasks.Task.FromResult(124); + } + + static async System.Threading.Tasks.Task Main() + { + var arr = new int[] { 1 }; + await M1(arr); + System.Console.WriteLine(arr[0]); + } +} +"; + CompileAndVerifyWithIndexAndRange(src, expectedOutput: +@" +125 +").VerifyDiagnostics(); + } + + [Fact] + public void PatternIndexArrayAndAwait_07() + { + var src = @" +class C +{ + static async System.Threading.Tasks.Task M1(int[][] arr) + { + arr[^1][0] += await System.Threading.Tasks.Task.FromResult(124); + } + + static async System.Threading.Tasks.Task Main() + { + var arr = new[] { new[] { 1 } }; + await M1(arr); + System.Console.WriteLine(arr[0][0]); + } +} +"; + CompileAndVerifyWithIndexAndRange(src, expectedOutput: +@" +125 +").VerifyDiagnostics(); + } } } From b454a6b38fd9b2071ddbf4f13cc992dc4a770903 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Thu, 6 Jan 2022 07:17:07 -0800 Subject: [PATCH 2/2] Add a test --- .../Test/Emit/CodeGen/IndexAndRangeTests.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs index 59752013a5dc6..668905cf2ed05 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs @@ -3765,5 +3765,27 @@ static async System.Threading.Tasks.Task Main() 125 ").VerifyDiagnostics(); } + + [Fact] + public void PatternIndexArrayAndAwait_08() + { + var src = @" +class C +{ + static async System.Threading.Tasks.Task M1((int x, int y)[] arr) + { + (arr[1..][^1].x, arr[1..][0].y) = (123, await System.Threading.Tasks.Task.FromResult(124)); + } + + static async System.Threading.Tasks.Task Main() + { + var arr = new (int x, int y)[5]; + await M1(arr); + System.Console.WriteLine(""Done""); + } +} +"; + CompileAndVerifyWithIndexAndRange(src, expectedOutput: "Done").VerifyDiagnostics(); + } } }