diff --git a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncIteratorMethodToStateMachineRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncIteratorMethodToStateMachineRewriter.cs index 496c04f657904..26c94761926bf 100644 --- a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncIteratorMethodToStateMachineRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncIteratorMethodToStateMachineRewriter.cs @@ -27,7 +27,7 @@ internal sealed class AsyncIteratorMethodToStateMachineRewriter : AsyncMethodToS /// Where should we jump to to continue the execution of disposal path. /// /// Initially, this is the method's return value label (). - /// Inside a `try` or `catch` with a `finally`, we'll use the label directly preceding the `finally`. + /// Inside a `try` or `catch` with a `finally`, we'll use the label directly following the `finally`. /// Inside a `try` or `catch` with an extracted `finally`, we will use the label preceding the extracted `finally`. /// Inside a `finally`, we'll have no/null label (disposal continues without a jump). /// @@ -351,7 +351,8 @@ private BoundExpressionStatement SetDisposeMode(bool value) /// /// An async-iterator state machine has a flag indicating "dispose mode". - /// We enter dispose mode by calling DisposeAsync() when the state machine is paused on a `yield return`. + /// We enter dispose mode by calling DisposeAsync() when the state machine is paused on a `yield return`, + /// or by reaching a `yield break`. /// DisposeAsync() will resume execution of the state machine from that state (using existing dispatch mechanism /// to restore execution from a given state, without executing other code to get there). /// @@ -366,21 +367,11 @@ private BoundExpressionStatement SetDisposeMode(bool value) public override BoundNode VisitTryStatement(BoundTryStatement node) { var savedDisposalLabel = _currentDisposalLabel; + LabelSymbol afterFinally = null; if (node.FinallyBlockOpt is object) { - var finallyEntry = F.GenerateLabel("finallyEntry"); - _currentDisposalLabel = finallyEntry; - - // Add finallyEntry label: - // try - // { - // ... - // finallyEntry: - // } - - node = node.Update( - tryBlock: F.Block(node.TryBlock, F.Label(finallyEntry)), - node.CatchBlocks, node.FinallyBlockOpt, node.FinallyLabelOpt, node.PreferFaultHandler); + afterFinally = F.GenerateLabel("afterFinally"); + _currentDisposalLabel = afterFinally; } else if (node.FinallyLabelOpt is object) { @@ -389,6 +380,14 @@ public override BoundNode VisitTryStatement(BoundTryStatement node) var result = (BoundStatement)base.VisitTryStatement(node); + if (afterFinally != null) + { + // Append a label immediately after the try-catch-finally statement, + // which disposal within `try`/`catch` blocks jumps to in order to pass control flow to the `finally` block implicitly: + // tryEnd: + result = F.Block(result, F.Label(afterFinally)); + } + _currentDisposalLabel = savedDisposalLabel; if (node.FinallyBlockOpt != null && _currentDisposalLabel is object) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs index b64cdeddde990..66a25aab0e098 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs @@ -4691,7 +4691,7 @@ public async System.Collections.Generic.IAsyncEnumerator GetAsyncEnumerator CompileAndVerify(comp, expectedOutput: expectedOutput); } - [Theory] + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/79124")] [InlineData(2, "1 Break Throw Caught Finally END DISPOSAL DONE")] public void TryFinally_YieldBreakInDisposeMode(int iterations, string expectedOutput) { @@ -4728,16 +4728,11 @@ public static async System.Collections.Generic.IAsyncEnumerable M() } }"; var comp = CreateCompilationWithAsyncIterator(new[] { Run(iterations), source }, options: TestOptions.DebugExe); - comp.VerifyDiagnostics(); - var verifier = CompileAndVerify(comp, expectedOutput: expectedOutput, - verify: Verification.FailsILVerify with - { - ILVerifyMessage = "[MoveNext]: Leave into try block. { Offset = 0x11a }" - }); + var verifier = CompileAndVerify(comp, expectedOutput: expectedOutput).VerifyDiagnostics(); verifier.VerifyIL("C.d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", """ { - // Code size 414 (0x19e) + // Code size 412 (0x19c) .maxstack 3 .locals init (int V_0, System.Runtime.CompilerServices.TaskAwaiter V_1, @@ -4764,7 +4759,7 @@ .locals init (int V_0, IL_002c: ldarg.0 IL_002d: ldfld "bool C.d__0.<>w__disposeMode" IL_0032: brfalse.s IL_0039 - IL_0034: leave IL_0167 + IL_0034: leave IL_0165 IL_0039: ldarg.0 IL_003a: ldc.i4.m1 IL_003b: dup @@ -4779,7 +4774,7 @@ .locals init (int V_0, IL_004d: dup IL_004e: stloc.0 IL_004f: stfld "int C.d__0.<>1__state" - IL_0054: leave IL_0190 + IL_0054: leave IL_018e IL_0059: ldarg.0 IL_005a: ldc.i4.m1 IL_005b: dup @@ -4788,7 +4783,7 @@ .locals init (int V_0, IL_0062: ldarg.0 IL_0063: ldfld "bool C.d__0.<>w__disposeMode" IL_0068: brfalse.s IL_006f - IL_006a: leave IL_0167 + IL_006a: leave IL_0165 IL_006f: call "System.Threading.Tasks.Task System.Threading.Tasks.Task.CompletedTask.get" IL_0074: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()" IL_0079: stloc.1 @@ -4811,7 +4806,7 @@ .locals init (int V_0, IL_009d: ldloca.s V_2 IL_009f: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.AwaitUnsafeOnCompletedd__0>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__0)" IL_00a4: nop - IL_00a5: leave IL_019d + IL_00a5: leave IL_019b IL_00aa: ldarg.0 IL_00ab: ldfld "System.Runtime.CompilerServices.TaskAwaiter C.d__0.<>u__1" IL_00b0: stloc.1 @@ -4840,103 +4835,102 @@ .locals init (int V_0, IL_00db: ldarg.0 IL_00dc: ldc.i4.1 IL_00dd: stfld "bool C.d__0.<>w__disposeMode" - IL_00e2: br.s IL_00e4 - IL_00e4: leave.s IL_00f9 + IL_00e2: leave.s IL_00f7 } finally { - IL_00e6: ldloc.0 - IL_00e7: ldc.i4.m1 - IL_00e8: bne.un.s IL_00f8 - IL_00ea: nop - IL_00eb: ldstr "Throw " - IL_00f0: call "void System.Console.Write(string)" - IL_00f5: nop - IL_00f6: ldnull - IL_00f7: throw - IL_00f8: endfinally + IL_00e4: ldloc.0 + IL_00e5: ldc.i4.m1 + IL_00e6: bne.un.s IL_00f6 + IL_00e8: nop + IL_00e9: ldstr "Throw " + IL_00ee: call "void System.Console.Write(string)" + IL_00f3: nop + IL_00f4: ldnull + IL_00f5: throw + IL_00f6: endfinally } - IL_00f9: ldarg.0 - IL_00fa: ldfld "bool C.d__0.<>w__disposeMode" - IL_00ff: brfalse.s IL_0103 - IL_0101: br.s IL_0104 - IL_0103: nop - IL_0104: leave.s IL_011c + IL_00f7: ldarg.0 + IL_00f8: ldfld "bool C.d__0.<>w__disposeMode" + IL_00fd: brfalse.s IL_0101 + IL_00ff: leave.s IL_012e + IL_0101: nop + IL_0102: leave.s IL_011a } catch object { - IL_0106: pop - IL_0107: nop - IL_0108: ldstr "Caught " - IL_010d: call "void System.Console.Write(string)" - IL_0112: nop - IL_0113: ldarg.0 - IL_0114: ldc.i4.1 - IL_0115: stfld "bool C.d__0.<>w__disposeMode" - IL_011a: leave.s IL_0104 + IL_0104: pop + IL_0105: nop + IL_0106: ldstr "Caught " + IL_010b: call "void System.Console.Write(string)" + IL_0110: nop + IL_0111: ldarg.0 + IL_0112: ldc.i4.1 + IL_0113: stfld "bool C.d__0.<>w__disposeMode" + IL_0118: leave.s IL_012e } - IL_011c: leave.s IL_0130 + IL_011a: leave.s IL_012e } finally { - IL_011e: ldloc.0 - IL_011f: ldc.i4.m1 - IL_0120: bne.un.s IL_012f - IL_0122: nop - IL_0123: ldstr "Finally " - IL_0128: call "void System.Console.Write(string)" - IL_012d: nop - IL_012e: nop - IL_012f: endfinally + IL_011c: ldloc.0 + IL_011d: ldc.i4.m1 + IL_011e: bne.un.s IL_012d + IL_0120: nop + IL_0121: ldstr "Finally " + IL_0126: call "void System.Console.Write(string)" + IL_012b: nop + IL_012c: nop + IL_012d: endfinally } - IL_0130: ldarg.0 - IL_0131: ldfld "bool C.d__0.<>w__disposeMode" - IL_0136: brfalse.s IL_013a - IL_0138: leave.s IL_0167 - IL_013a: leave.s IL_0167 + IL_012e: ldarg.0 + IL_012f: ldfld "bool C.d__0.<>w__disposeMode" + IL_0134: brfalse.s IL_0138 + IL_0136: leave.s IL_0165 + IL_0138: leave.s IL_0165 } catch System.Exception { - IL_013c: stloc.3 - IL_013d: ldarg.0 - IL_013e: ldc.i4.s -2 - IL_0140: stfld "int C.d__0.<>1__state" - IL_0145: ldarg.0 - IL_0146: ldc.i4.0 - IL_0147: stfld "int C.d__0.<>2__current" - IL_014c: ldarg.0 - IL_014d: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder" - IL_0152: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" - IL_0157: nop - IL_0158: ldarg.0 - IL_0159: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" - IL_015e: ldloc.3 - IL_015f: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetException(System.Exception)" - IL_0164: nop - IL_0165: leave.s IL_019d + IL_013a: stloc.3 + IL_013b: ldarg.0 + IL_013c: ldc.i4.s -2 + IL_013e: stfld "int C.d__0.<>1__state" + IL_0143: ldarg.0 + IL_0144: ldc.i4.0 + IL_0145: stfld "int C.d__0.<>2__current" + IL_014a: ldarg.0 + IL_014b: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder" + IL_0150: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" + IL_0155: nop + IL_0156: ldarg.0 + IL_0157: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" + IL_015c: ldloc.3 + IL_015d: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetException(System.Exception)" + IL_0162: nop + IL_0163: leave.s IL_019b } - IL_0167: ldarg.0 - IL_0168: ldc.i4.s -2 - IL_016a: stfld "int C.d__0.<>1__state" - IL_016f: ldarg.0 - IL_0170: ldc.i4.0 - IL_0171: stfld "int C.d__0.<>2__current" - IL_0176: ldarg.0 - IL_0177: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder" - IL_017c: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" - IL_0181: nop - IL_0182: ldarg.0 - IL_0183: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" - IL_0188: ldc.i4.0 - IL_0189: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" - IL_018e: nop - IL_018f: ret - IL_0190: ldarg.0 - IL_0191: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" - IL_0196: ldc.i4.1 - IL_0197: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" - IL_019c: nop - IL_019d: ret + IL_0165: ldarg.0 + IL_0166: ldc.i4.s -2 + IL_0168: stfld "int C.d__0.<>1__state" + IL_016d: ldarg.0 + IL_016e: ldc.i4.0 + IL_016f: stfld "int C.d__0.<>2__current" + IL_0174: ldarg.0 + IL_0175: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder" + IL_017a: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" + IL_017f: nop + IL_0180: ldarg.0 + IL_0181: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" + IL_0186: ldc.i4.0 + IL_0187: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" + IL_018c: nop + IL_018d: ret + IL_018e: ldarg.0 + IL_018f: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" + IL_0194: ldc.i4.1 + IL_0195: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" + IL_019a: nop + IL_019b: ret } """); } @@ -6527,6 +6521,331 @@ public static async System.Collections.Generic.IAsyncEnumerable M() CompileAndVerify(comp, expectedOutput: expectedOutput); } + [Fact] + public void TryFinally_01() + { + // await in a catch/finally (so the catch and finally are extracted/rewritten), execution path through catch + string source = """ +using static System.Console; +public class C +{ + public static async System.Collections.Generic.IAsyncEnumerable M() + { + yield return 1; + + try + { + Write("Throw "); + throw new System.Exception("thrown"); + } + catch + { + await System.Threading.Tasks.Task.CompletedTask; + Write("Caught "); + yield break; + } + finally + { + await System.Threading.Tasks.Task.CompletedTask; + Write("Finally "); + } + } +} +"""; + var comp = CreateCompilationWithAsyncIterator(new[] { Run(2), source }, options: TestOptions.DebugExe); + var verifier = CompileAndVerify(comp, expectedOutput: "1 Throw Caught Finally END DISPOSAL DONE").VerifyDiagnostics(); + + verifier.VerifyIL("C.d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", """ +{ + // Code size 647 (0x287) + .maxstack 3 + .locals init (int V_0, + object V_1, + int V_2, + System.Runtime.CompilerServices.TaskAwaiter V_3, + C.d__0 V_4, + object V_5, + System.Runtime.CompilerServices.TaskAwaiter V_6, + System.Exception V_7) + IL_0000: ldarg.0 + IL_0001: ldfld "int C.d__0.<>1__state" + IL_0006: stloc.0 + .try + { + IL_0007: ldloc.0 + IL_0008: ldc.i4.s -4 + IL_000a: sub + IL_000b: switch ( + IL_002a, + IL_002c, + IL_0035, + IL_0035, + IL_002e, + IL_0030) + IL_0028: br.s IL_0035 + IL_002a: br.s IL_0062 + IL_002c: br.s IL_0035 + IL_002e: br.s IL_0086 + IL_0030: br IL_0193 + IL_0035: ldarg.0 + IL_0036: ldfld "bool C.d__0.<>w__disposeMode" + IL_003b: brfalse.s IL_0042 + IL_003d: leave IL_0242 + IL_0042: ldarg.0 + IL_0043: ldc.i4.m1 + IL_0044: dup + IL_0045: stloc.0 + IL_0046: stfld "int C.d__0.<>1__state" + IL_004b: nop + IL_004c: ldarg.0 + IL_004d: ldc.i4.1 + IL_004e: stfld "int C.d__0.<>2__current" + IL_0053: ldarg.0 + IL_0054: ldc.i4.s -4 + IL_0056: dup + IL_0057: stloc.0 + IL_0058: stfld "int C.d__0.<>1__state" + IL_005d: leave IL_0279 + IL_0062: ldarg.0 + IL_0063: ldc.i4.m1 + IL_0064: dup + IL_0065: stloc.0 + IL_0066: stfld "int C.d__0.<>1__state" + IL_006b: ldarg.0 + IL_006c: ldfld "bool C.d__0.<>w__disposeMode" + IL_0071: brfalse.s IL_0078 + IL_0073: leave IL_0242 + IL_0078: ldarg.0 + IL_0079: ldnull + IL_007a: stfld "object C.d__0.<>s__1" + IL_007f: ldarg.0 + IL_0080: ldc.i4.0 + IL_0081: stfld "int C.d__0.<>s__2" + IL_0086: nop + .try + { + IL_0087: ldloc.0 + IL_0088: brfalse.s IL_008c + IL_008a: br.s IL_008e + IL_008c: br.s IL_0107 + IL_008e: ldarg.0 + IL_008f: ldc.i4.0 + IL_0090: stfld "int C.d__0.<>s__4" + .try + { + IL_0095: nop + IL_0096: ldstr "Throw " + IL_009b: call "void System.Console.Write(string)" + IL_00a0: nop + IL_00a1: ldstr "thrown" + IL_00a6: newobj "System.Exception..ctor(string)" + IL_00ab: throw + } + catch object + { + IL_00ac: stloc.1 + IL_00ad: ldarg.0 + IL_00ae: ldloc.1 + IL_00af: stfld "object C.d__0.<>s__3" + IL_00b4: ldarg.0 + IL_00b5: ldc.i4.1 + IL_00b6: stfld "int C.d__0.<>s__4" + IL_00bb: leave.s IL_00bd + } + IL_00bd: ldarg.0 + IL_00be: ldfld "int C.d__0.<>s__4" + IL_00c3: stloc.2 + IL_00c4: ldloc.2 + IL_00c5: ldc.i4.1 + IL_00c6: beq.s IL_00ca + IL_00c8: br.s IL_013f + IL_00ca: nop + IL_00cb: call "System.Threading.Tasks.Task System.Threading.Tasks.Task.CompletedTask.get" + IL_00d0: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()" + IL_00d5: stloc.3 + IL_00d6: ldloca.s V_3 + IL_00d8: call "bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get" + IL_00dd: brtrue.s IL_0123 + IL_00df: ldarg.0 + IL_00e0: ldc.i4.0 + IL_00e1: dup + IL_00e2: stloc.0 + IL_00e3: stfld "int C.d__0.<>1__state" + IL_00e8: ldarg.0 + IL_00e9: ldloc.3 + IL_00ea: stfld "System.Runtime.CompilerServices.TaskAwaiter C.d__0.<>u__1" + IL_00ef: ldarg.0 + IL_00f0: stloc.s V_4 + IL_00f2: ldarg.0 + IL_00f3: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder" + IL_00f8: ldloca.s V_3 + IL_00fa: ldloca.s V_4 + IL_00fc: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.AwaitUnsafeOnCompletedd__0>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__0)" + IL_0101: nop + IL_0102: leave IL_0286 + IL_0107: ldarg.0 + IL_0108: ldfld "System.Runtime.CompilerServices.TaskAwaiter C.d__0.<>u__1" + IL_010d: stloc.3 + IL_010e: ldarg.0 + IL_010f: ldflda "System.Runtime.CompilerServices.TaskAwaiter C.d__0.<>u__1" + IL_0114: initobj "System.Runtime.CompilerServices.TaskAwaiter" + IL_011a: ldarg.0 + IL_011b: ldc.i4.m1 + IL_011c: dup + IL_011d: stloc.0 + IL_011e: stfld "int C.d__0.<>1__state" + IL_0123: ldloca.s V_3 + IL_0125: call "void System.Runtime.CompilerServices.TaskAwaiter.GetResult()" + IL_012a: nop + IL_012b: ldstr "Caught " + IL_0130: call "void System.Console.Write(string)" + IL_0135: nop + IL_0136: ldarg.0 + IL_0137: ldc.i4.1 + IL_0138: stfld "bool C.d__0.<>w__disposeMode" + IL_013d: leave.s IL_0154 + IL_013f: ldarg.0 + IL_0140: ldnull + IL_0141: stfld "object C.d__0.<>s__3" + IL_0146: leave.s IL_0154 + } + catch object + { + IL_0148: stloc.s V_5 + IL_014a: ldarg.0 + IL_014b: ldloc.s V_5 + IL_014d: stfld "object C.d__0.<>s__1" + IL_0152: leave.s IL_0154 + } + IL_0154: nop + IL_0155: call "System.Threading.Tasks.Task System.Threading.Tasks.Task.CompletedTask.get" + IL_015a: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()" + IL_015f: stloc.s V_6 + IL_0161: ldloca.s V_6 + IL_0163: call "bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get" + IL_0168: brtrue.s IL_01b0 + IL_016a: ldarg.0 + IL_016b: ldc.i4.1 + IL_016c: dup + IL_016d: stloc.0 + IL_016e: stfld "int C.d__0.<>1__state" + IL_0173: ldarg.0 + IL_0174: ldloc.s V_6 + IL_0176: stfld "System.Runtime.CompilerServices.TaskAwaiter C.d__0.<>u__1" + IL_017b: ldarg.0 + IL_017c: stloc.s V_4 + IL_017e: ldarg.0 + IL_017f: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder" + IL_0184: ldloca.s V_6 + IL_0186: ldloca.s V_4 + IL_0188: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.AwaitUnsafeOnCompletedd__0>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__0)" + IL_018d: nop + IL_018e: leave IL_0286 + IL_0193: ldarg.0 + IL_0194: ldfld "System.Runtime.CompilerServices.TaskAwaiter C.d__0.<>u__1" + IL_0199: stloc.s V_6 + IL_019b: ldarg.0 + IL_019c: ldflda "System.Runtime.CompilerServices.TaskAwaiter C.d__0.<>u__1" + IL_01a1: initobj "System.Runtime.CompilerServices.TaskAwaiter" + IL_01a7: ldarg.0 + IL_01a8: ldc.i4.m1 + IL_01a9: dup + IL_01aa: stloc.0 + IL_01ab: stfld "int C.d__0.<>1__state" + IL_01b0: ldloca.s V_6 + IL_01b2: call "void System.Runtime.CompilerServices.TaskAwaiter.GetResult()" + IL_01b7: nop + IL_01b8: ldstr "Finally " + IL_01bd: call "void System.Console.Write(string)" + IL_01c2: nop + IL_01c3: nop + IL_01c4: ldarg.0 + IL_01c5: ldfld "object C.d__0.<>s__1" + IL_01ca: stloc.s V_5 + IL_01cc: ldloc.s V_5 + IL_01ce: brfalse.s IL_01ed + IL_01d0: ldloc.s V_5 + IL_01d2: isinst "System.Exception" + IL_01d7: stloc.s V_7 + IL_01d9: ldloc.s V_7 + IL_01db: brtrue.s IL_01e0 + IL_01dd: ldloc.s V_5 + IL_01df: throw + IL_01e0: ldloc.s V_7 + IL_01e2: call "System.Runtime.ExceptionServices.ExceptionDispatchInfo System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(System.Exception)" + IL_01e7: callvirt "void System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()" + IL_01ec: nop + IL_01ed: ldarg.0 + IL_01ee: ldfld "int C.d__0.<>s__2" + IL_01f3: pop + IL_01f4: ldarg.0 + IL_01f5: ldfld "bool C.d__0.<>w__disposeMode" + IL_01fa: brfalse.s IL_01fe + IL_01fc: leave.s IL_0242 + IL_01fe: ldarg.0 + IL_01ff: ldnull + IL_0200: stfld "object C.d__0.<>s__1" + IL_0205: ldnull + IL_0206: throw + } + catch System.Exception + { + IL_0207: stloc.s V_7 + IL_0209: ldarg.0 + IL_020a: ldc.i4.s -2 + IL_020c: stfld "int C.d__0.<>1__state" + IL_0211: ldarg.0 + IL_0212: ldnull + IL_0213: stfld "object C.d__0.<>s__1" + IL_0218: ldarg.0 + IL_0219: ldnull + IL_021a: stfld "object C.d__0.<>s__3" + IL_021f: ldarg.0 + IL_0220: ldc.i4.0 + IL_0221: stfld "int C.d__0.<>2__current" + IL_0226: ldarg.0 + IL_0227: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder" + IL_022c: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" + IL_0231: nop + IL_0232: ldarg.0 + IL_0233: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" + IL_0238: ldloc.s V_7 + IL_023a: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetException(System.Exception)" + IL_023f: nop + IL_0240: leave.s IL_0286 + } + IL_0242: ldarg.0 + IL_0243: ldc.i4.s -2 + IL_0245: stfld "int C.d__0.<>1__state" + IL_024a: ldarg.0 + IL_024b: ldnull + IL_024c: stfld "object C.d__0.<>s__1" + IL_0251: ldarg.0 + IL_0252: ldnull + IL_0253: stfld "object C.d__0.<>s__3" + IL_0258: ldarg.0 + IL_0259: ldc.i4.0 + IL_025a: stfld "int C.d__0.<>2__current" + IL_025f: ldarg.0 + IL_0260: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder" + IL_0265: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" + IL_026a: nop + IL_026b: ldarg.0 + IL_026c: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" + IL_0271: ldc.i4.0 + IL_0272: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" + IL_0277: nop + IL_0278: ret + IL_0279: ldarg.0 + IL_027a: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" + IL_027f: ldc.i4.1 + IL_0280: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" + IL_0285: nop + IL_0286: ret +} +"""); + } + [Fact] public void AsyncIteratorWithAwaitOnly() { @@ -11379,8 +11698,8 @@ public static async IAsyncEnumerable AsAsyncEnumerable(this IEnumerable verify: Verification.Skipped); verifier.VerifyDiagnostics(); verifier.VerifyIL("C.d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", """ - { - // Code size 518 (0x206) + { + // Code size 520 (0x208) .maxstack 6 .locals init (int V_0, T V_1, //item @@ -11400,7 +11719,7 @@ .locals init (int V_0, IL_0014: ldarg.0 IL_0015: ldfld "bool C.d__0.<>w__disposeMode" IL_001a: brfalse.s IL_0021 - IL_001c: leave IL_01a5 + IL_001c: leave IL_01a7 IL_0021: ldarg.0 IL_0022: ldc.i4.m1 IL_0023: dup @@ -11457,7 +11776,7 @@ .locals init (int V_0, IL_00b5: ldloc.0 IL_00b6: ldc.i4.s -4 IL_00b8: beq.s IL_00f0 - IL_00ba: br.s IL_0115 + IL_00ba: br.s IL_0117 IL_00bc: ldarg.0 IL_00bd: ldfld "bool[] C.d__0.<>7__wrap1" IL_00c2: ldc.i4.5 @@ -11480,7 +11799,7 @@ .locals init (int V_0, IL_00e4: dup IL_00e5: stloc.0 IL_00e6: stfld "int C.d__0.<>1__state" - IL_00eb: leave IL_01f9 + IL_00eb: leave IL_01fb IL_00f0: ldarg.0 IL_00f1: ldc.i4.m1 IL_00f2: dup @@ -11488,110 +11807,111 @@ .locals init (int V_0, IL_00f4: stfld "int C.d__0.<>1__state" IL_00f9: ldarg.0 IL_00fa: ldfld "bool C.d__0.<>w__disposeMode" - IL_00ff: brtrue.s IL_0122 - IL_0101: ldarg.0 - IL_0102: ldfld "bool[] C.d__0.<>7__wrap1" - IL_0107: ldc.i4.4 - IL_0108: ldc.i4.1 - IL_0109: stelem.i1 - IL_010a: ldarg.0 - IL_010b: ldflda "System.Threading.CancellationToken C.d__0.cancellationToken" - IL_0110: call "void System.Threading.CancellationToken.ThrowIfCancellationRequested()" - IL_0115: ldarg.0 - IL_0116: ldfld "System.Collections.Generic.IEnumerator C.d__0.<>7__wrap2" - IL_011b: callvirt "bool System.Collections.IEnumerator.MoveNext()" - IL_0120: brtrue.s IL_00bc - IL_0122: leave.s IL_013c + IL_00ff: brfalse.s IL_0103 + IL_0101: leave.s IL_013e + IL_0103: ldarg.0 + IL_0104: ldfld "bool[] C.d__0.<>7__wrap1" + IL_0109: ldc.i4.4 + IL_010a: ldc.i4.1 + IL_010b: stelem.i1 + IL_010c: ldarg.0 + IL_010d: ldflda "System.Threading.CancellationToken C.d__0.cancellationToken" + IL_0112: call "void System.Threading.CancellationToken.ThrowIfCancellationRequested()" + IL_0117: ldarg.0 + IL_0118: ldfld "System.Collections.Generic.IEnumerator C.d__0.<>7__wrap2" + IL_011d: callvirt "bool System.Collections.IEnumerator.MoveNext()" + IL_0122: brtrue.s IL_00bc + IL_0124: leave.s IL_013e } finally { - IL_0124: ldloc.0 - IL_0125: ldc.i4.m1 - IL_0126: bne.un.s IL_013b - IL_0128: ldarg.0 - IL_0129: ldfld "System.Collections.Generic.IEnumerator C.d__0.<>7__wrap2" - IL_012e: brfalse.s IL_013b - IL_0130: ldarg.0 - IL_0131: ldfld "System.Collections.Generic.IEnumerator C.d__0.<>7__wrap2" - IL_0136: callvirt "void System.IDisposable.Dispose()" - IL_013b: endfinally + IL_0126: ldloc.0 + IL_0127: ldc.i4.m1 + IL_0128: bne.un.s IL_013d + IL_012a: ldarg.0 + IL_012b: ldfld "System.Collections.Generic.IEnumerator C.d__0.<>7__wrap2" + IL_0130: brfalse.s IL_013d + IL_0132: ldarg.0 + IL_0133: ldfld "System.Collections.Generic.IEnumerator C.d__0.<>7__wrap2" + IL_0138: callvirt "void System.IDisposable.Dispose()" + IL_013d: endfinally } - IL_013c: ldarg.0 - IL_013d: ldfld "bool C.d__0.<>w__disposeMode" - IL_0142: brfalse.s IL_0146 - IL_0144: leave.s IL_01a5 - IL_0146: ldarg.0 - IL_0147: ldnull - IL_0148: stfld "System.Collections.Generic.IEnumerator C.d__0.<>7__wrap2" - IL_014d: leave.s IL_01a5 + IL_013e: ldarg.0 + IL_013f: ldfld "bool C.d__0.<>w__disposeMode" + IL_0144: brfalse.s IL_0148 + IL_0146: leave.s IL_01a7 + IL_0148: ldarg.0 + IL_0149: ldnull + IL_014a: stfld "System.Collections.Generic.IEnumerator C.d__0.<>7__wrap2" + IL_014f: leave.s IL_01a7 } catch System.Exception { - IL_014f: stloc.2 - IL_0150: ldarg.0 - IL_0151: ldc.i4.s -2 - IL_0153: stfld "int C.d__0.<>1__state" - IL_0158: ldarg.0 - IL_0159: ldnull - IL_015a: stfld "bool[] C.d__0.<>7__wrap1" - IL_015f: ldarg.0 - IL_0160: ldnull - IL_0161: stfld "System.Collections.Generic.IEnumerator C.d__0.<>7__wrap2" - IL_0166: ldarg.0 - IL_0167: ldfld "System.Threading.CancellationTokenSource C.d__0.<>x__combinedTokens" - IL_016c: brfalse.s IL_0180 - IL_016e: ldarg.0 - IL_016f: ldfld "System.Threading.CancellationTokenSource C.d__0.<>x__combinedTokens" - IL_0174: callvirt "void System.Threading.CancellationTokenSource.Dispose()" - IL_0179: ldarg.0 - IL_017a: ldnull - IL_017b: stfld "System.Threading.CancellationTokenSource C.d__0.<>x__combinedTokens" - IL_0180: ldarg.0 - IL_0181: ldflda "T C.d__0.<>2__current" - IL_0186: initobj "T" - IL_018c: ldarg.0 - IL_018d: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder" - IL_0192: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" - IL_0197: ldarg.0 - IL_0198: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" - IL_019d: ldloc.2 - IL_019e: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetException(System.Exception)" - IL_01a3: leave.s IL_0205 + IL_0151: stloc.2 + IL_0152: ldarg.0 + IL_0153: ldc.i4.s -2 + IL_0155: stfld "int C.d__0.<>1__state" + IL_015a: ldarg.0 + IL_015b: ldnull + IL_015c: stfld "bool[] C.d__0.<>7__wrap1" + IL_0161: ldarg.0 + IL_0162: ldnull + IL_0163: stfld "System.Collections.Generic.IEnumerator C.d__0.<>7__wrap2" + IL_0168: ldarg.0 + IL_0169: ldfld "System.Threading.CancellationTokenSource C.d__0.<>x__combinedTokens" + IL_016e: brfalse.s IL_0182 + IL_0170: ldarg.0 + IL_0171: ldfld "System.Threading.CancellationTokenSource C.d__0.<>x__combinedTokens" + IL_0176: callvirt "void System.Threading.CancellationTokenSource.Dispose()" + IL_017b: ldarg.0 + IL_017c: ldnull + IL_017d: stfld "System.Threading.CancellationTokenSource C.d__0.<>x__combinedTokens" + IL_0182: ldarg.0 + IL_0183: ldflda "T C.d__0.<>2__current" + IL_0188: initobj "T" + IL_018e: ldarg.0 + IL_018f: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder" + IL_0194: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" + IL_0199: ldarg.0 + IL_019a: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" + IL_019f: ldloc.2 + IL_01a0: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetException(System.Exception)" + IL_01a5: leave.s IL_0207 } - IL_01a5: ldarg.0 - IL_01a6: ldc.i4.s -2 - IL_01a8: stfld "int C.d__0.<>1__state" - IL_01ad: ldarg.0 - IL_01ae: ldnull - IL_01af: stfld "bool[] C.d__0.<>7__wrap1" - IL_01b4: ldarg.0 - IL_01b5: ldnull - IL_01b6: stfld "System.Collections.Generic.IEnumerator C.d__0.<>7__wrap2" - IL_01bb: ldarg.0 - IL_01bc: ldfld "System.Threading.CancellationTokenSource C.d__0.<>x__combinedTokens" - IL_01c1: brfalse.s IL_01d5 - IL_01c3: ldarg.0 - IL_01c4: ldfld "System.Threading.CancellationTokenSource C.d__0.<>x__combinedTokens" - IL_01c9: callvirt "void System.Threading.CancellationTokenSource.Dispose()" - IL_01ce: ldarg.0 - IL_01cf: ldnull - IL_01d0: stfld "System.Threading.CancellationTokenSource C.d__0.<>x__combinedTokens" - IL_01d5: ldarg.0 - IL_01d6: ldflda "T C.d__0.<>2__current" - IL_01db: initobj "T" - IL_01e1: ldarg.0 - IL_01e2: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder" - IL_01e7: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" - IL_01ec: ldarg.0 - IL_01ed: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" - IL_01f2: ldc.i4.0 - IL_01f3: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" - IL_01f8: ret - IL_01f9: ldarg.0 - IL_01fa: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" - IL_01ff: ldc.i4.1 - IL_0200: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" - IL_0205: ret + IL_01a7: ldarg.0 + IL_01a8: ldc.i4.s -2 + IL_01aa: stfld "int C.d__0.<>1__state" + IL_01af: ldarg.0 + IL_01b0: ldnull + IL_01b1: stfld "bool[] C.d__0.<>7__wrap1" + IL_01b6: ldarg.0 + IL_01b7: ldnull + IL_01b8: stfld "System.Collections.Generic.IEnumerator C.d__0.<>7__wrap2" + IL_01bd: ldarg.0 + IL_01be: ldfld "System.Threading.CancellationTokenSource C.d__0.<>x__combinedTokens" + IL_01c3: brfalse.s IL_01d7 + IL_01c5: ldarg.0 + IL_01c6: ldfld "System.Threading.CancellationTokenSource C.d__0.<>x__combinedTokens" + IL_01cb: callvirt "void System.Threading.CancellationTokenSource.Dispose()" + IL_01d0: ldarg.0 + IL_01d1: ldnull + IL_01d2: stfld "System.Threading.CancellationTokenSource C.d__0.<>x__combinedTokens" + IL_01d7: ldarg.0 + IL_01d8: ldflda "T C.d__0.<>2__current" + IL_01dd: initobj "T" + IL_01e3: ldarg.0 + IL_01e4: ldflda "System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder" + IL_01e9: call "void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()" + IL_01ee: ldarg.0 + IL_01ef: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" + IL_01f4: ldc.i4.0 + IL_01f5: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" + IL_01fa: ret + IL_01fb: ldarg.0 + IL_01fc: ldflda "System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore C.d__0.<>v__promiseOfValueOrEnd" + IL_0201: ldc.i4.1 + IL_0202: call "void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore.SetResult(bool)" + IL_0207: ret } """); }