From 1c30a57f262077a3094cabc6fc24857ec7fec53d Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Wed, 15 Apr 2015 14:45:41 -0700 Subject: [PATCH] Ensure that partially assigned structures are properly hoisted by async rewriter. Fixes #1942. --- .../IteratorAndAsyncCaptureWalker.cs | 34 +++++++++++----- .../Test/Emit/CodeGen/CodeGenAsyncTests.cs | 40 +++++++++++++++++++ .../Test/Emit/CodeGen/CodeGenAsyncTests.vb | 37 +++++++++++++++++ 3 files changed, 102 insertions(+), 9 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/IteratorAndAsyncCaptureWalker.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/IteratorAndAsyncCaptureWalker.cs index f31509809f9..ec590b23994 100644 --- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/IteratorAndAsyncCaptureWalker.cs +++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/IteratorAndAsyncCaptureWalker.cs @@ -130,17 +130,33 @@ private void MarkLocalsUnassigned() for (int i = 0; i < nextVariableSlot; i++) { var symbol = variableBySlot[i].Symbol; - var local = symbol as LocalSymbol; - if ((object)local != null && !local.IsConst) - { - SetSlotState(i, false); - continue; - } - var parameter = symbol as ParameterSymbol; - if ((object)parameter != null) + if ((object)symbol != null) { - SetSlotState(i, false); + switch (symbol.Kind) + { + case SymbolKind.Local: + if (!((LocalSymbol)symbol).IsConst) + { + SetSlotState(i, false); + } + break; + + case SymbolKind.Parameter: + SetSlotState(i, false); + break; + + case SymbolKind.Field: + if (!((FieldSymbol)symbol).IsConst) + { + SetSlotState(i, false); + } + break; + + default: + Debug.Assert(false); + break; + } } } } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs index 8b2649738b5..fbcc3b2591b 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs @@ -3288,5 +3288,45 @@ .maxstack 3 }", sequencePoints: "Test+d__2.MoveNext"); } + + [Fact, WorkItem(1942, "https://github.com/dotnet/roslyn/issues/1942")] + public void HoistStructure() + { + var source = @" +using System; +using System.Threading.Tasks; +namespace ConsoleApp +{ + struct TestStruct + { + public long i; + public long j; + } + class Program + { + static async Task TestAsync() + { + TestStruct t; + t.i = 12; + Console.WriteLine(""Before {0}"", t.i); // emits ""Before 12"" + await Task.Delay(100); + Console.WriteLine(""After {0}"", t.i); // emits ""After 0"" expecting ""After 12"" + } + static void Main(string[] args) + { + TestAsync().Wait(); + } + } +}"; + + var expectedOutput = @"Before 12 +After 12"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + + CompileAndVerify(comp, expectedOutput: expectedOutput); + + CompileAndVerify(comp.WithOptions(TestOptions.ReleaseExe), expectedOutput: expectedOutput); + } } } diff --git a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenAsyncTests.vb b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenAsyncTests.vb index f21d0d761cb..ad4c348478e 100644 --- a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenAsyncTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenAsyncTests.vb @@ -8386,6 +8386,43 @@ End Class at C.VB$StateMachine_2_M.MoveNext()") End Sub + + Public Sub HoistStructure() + Dim source = + + +Imports System +Imports System.Threading.Tasks + +Structure TestStruct + Public i As Long + Public j As Long +End Structure + +Class Program + Shared Async Function TestAsync() As Task + Dim t As TestStruct + t.i = 12 + Console.WriteLine("Before {0}", t.i) + Await Task.Delay(100) + Console.WriteLine("After {0}", t.i) + End Function + + Shared Sub Main() + TestAsync().Wait() + End Sub +End Class + + + + Dim expectedOutput = + + Dim compilation = CompilationUtils.CreateCompilationWithReferences(source, references:=Me.LatestReferences, options:=TestOptions.DebugExe) + CompileAndVerify(compilation, expectedOutput:=expectedOutput) + + CompileAndVerify(compilation.WithOptions(TestOptions.ReleaseExe), expectedOutput:=expectedOutput) + End Sub End Class End Namespace -- GitLab