Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 14, 2025

Fixes #[issue number from problem statement]

Problem

When a yield break statement appeared in a catch block within a try-catch-finally structure in an async iterator method, the compiler generated invalid IL that failed ILVerify with the error:

[MoveNext]: Leave into try block. { Offset = 0x11a }

This occurred because the compiler placed a finallyEntry label at the end of the try block to handle disposal mode jumps. When a yield break in a catch block tried to leave to this label, it created invalid IL - you cannot leave from a catch block into its associated try block.

Example

public static async IAsyncEnumerable<int> M()
{
    try
    {
        try { yield break; }
        finally { throw null; }
    }
    catch
    {
        yield break;  // This generated invalid IL
    }
    finally { }
}

Solution

Modified AsyncIteratorMethodToStateMachineRewriter.cs to intelligently place the finallyEntry label based on whether the try statement has catch blocks:

  • Without catch blocks: Place the label at the end of the try block (original behavior, valid IL)
  • With catch blocks: Place the label after the entire try-catch-finally structure (new behavior, valid IL)

This ensures both try blocks and catch blocks can validly leave to the finallyEntry label, and the finally block executes properly before continuing disposal.

Testing

  • The TryFinally_YieldBreakInDisposeMode test now passes without requiring Verification.FailsILVerify
  • All 283 async iterator tests pass, confirming no regressions
  • The generated IL now passes ILVerify validation
Original prompt

This section details on the original issue you should resolve

<issue_title>ILVerify Failure: TryFinally_YieldBreakInDisposeMode</issue_title>
<issue_description>Version Used: c8b5f30

public void TryFinally_YieldBreakInDisposeMode(int iterations, string expectedOutput)
{
string source = @"
using static System.Console;
public class C
{
public static async System.Collections.Generic.IAsyncEnumerable<int> M()
{
yield return 1;
await System.Threading.Tasks.Task.CompletedTask;
try
{
try
{
Write(""Break "");
yield break;
}
finally
{
Write(""Throw "");
throw null;
}
}
catch
{
Write(""Caught "");
yield break;
}
finally
{
Write(""Finally "");
}
}
}";
var comp = CreateCompilationWithAsyncIterator(new[] { Run(iterations), source }, options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: expectedOutput);
}

When this test is run on .NET with ILVerify, the following warning is produced:

[MoveNext]: Leave into try block. { Offset = 0x11a }

</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #79124


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

When a yield break appears in a catch block inside a try-catch-finally structure, the compiler was generating invalid IL that caused ILVerify to fail with "Leave into try block".

The issue was that the finallyEntry label was placed at the end of the try block, and catch blocks would try to leave to this label, which is invalid IL (can't leave from catch into try).

The fix checks if a try-finally has catch blocks:
- If NO catch blocks: place finallyEntry at end of try block (original behavior, valid IL)
- If HAS catch blocks: place finallyEntry after the entire try-catch-finally structure (new behavior, valid IL)

This ensures both try and catch blocks can validly leave to the finallyEntry label.

Co-authored-by: jcouv <[email protected]>
@Copilot Copilot AI changed the title [WIP] Fix ILVerify failure in TryFinally test case Fix ILVerify failure: yield break in catch blocks within async iterators Oct 14, 2025
@Copilot Copilot AI requested a review from jcouv October 14, 2025 21:01
Copilot finished work on behalf of jcouv October 14, 2025 21:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ILVerify Failure: TryFinally_YieldBreakInDisposeMode

2 participants