Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Fix ILVerify failure: yield break in catch blocks within async iterators #80719

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
Copilot wants to merge 2 commits into main
base: main
Choose a base branch
Loading
from copilot/fix-ilverify-tryfinally

Conversation

Copy link
Contributor

@Copilot Copilot AI commented Oct 14, 2025
edited
Loading

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 <12466233+jcouv@users.noreply.github.com>
@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

Reviewers

@jcouv jcouv Awaiting requested review from jcouv

At least 1 approving review is required to merge this pull request.

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

ILVerify Failure: TryFinally_YieldBreakInDisposeMode

2 participants

AltStyle によって変換されたページ (->オリジナル) /