Browse Source

Fix #3908: use the async iterator element type for yield

Yield translation derived its target type only from synchronous enumerable
interfaces, leaving async iterator yields untyped and preserving compiler
boxing casts. Use the element type already recovered by the async decompiler.

Assisted-by: Copilot:gpt-5.6-sol:GitHub Copilot CLI
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 86d2918e-5a24-48b4-9a86-41d331ec3720
pull/3911/head
Sebastien Lebreton 2 months ago
parent
commit
eb6d341866
  1. 33
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncStreams.cs
  2. 3
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

33
ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncStreams.cs

@ -6,6 +6,12 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
public enum AsyncStreamColor
{
Red,
Green
}
public class AsyncStreams public class AsyncStreams
{ {
public static async IAsyncEnumerable<int> CountTo(int until) public static async IAsyncEnumerable<int> CountTo(int until)
@ -85,6 +91,33 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
await Task.Yield(); await Task.Yield();
} }
} }
public static async IAsyncEnumerable<IAsyncStreamEntry> ConstrainedGenericYield<T>(IAsyncEnumerable<T> items) where T : IAsyncStreamEntry
{
await foreach (T item in items)
{
yield return item;
}
}
public static IEnumerable<object> BoxedValues()
{
yield return true;
yield return 'a';
yield return AsyncStreamColor.Green;
}
public static async IAsyncEnumerable<object> BoxedValuesAsync()
{
yield return true;
await Task.Yield();
yield return 'a';
yield return AsyncStreamColor.Green;
}
}
public interface IAsyncStreamEntry
{
} }
public struct TestStruct public struct TestStruct

3
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -433,7 +433,8 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedStatement VisitYieldReturn(YieldReturn inst) protected internal override TranslatedStatement VisitYieldReturn(YieldReturn inst)
{ {
var elementType = currentFunction.ReturnType.GetElementTypeFromIEnumerable(typeSystem, true, out var isGeneric); var elementType = currentFunction.AsyncReturnType
?? currentFunction.ReturnType.GetElementTypeFromIEnumerable(typeSystem, true, out _);
var expr = exprBuilder.Translate(inst.Value, typeHint: elementType) var expr = exprBuilder.Translate(inst.Value, typeHint: elementType)
.ConvertTo(elementType, exprBuilder, allowImplicitConversion: true); .ConvertTo(elementType, exprBuilder, allowImplicitConversion: true);
return new YieldReturnStatement { return new YieldReturnStatement {

Loading…
Cancel
Save