Skip to content

Commit 9e281c5

Browse files
Fix anonymous-type lambda early-return emitting unresolvable cast
When a lambda's inferred return type contains an anonymous type and one branch returns null, the decompiler emitted an explicit cast such as `return (IEnumerable<<>f__AnonymousType0<int>>)null;`, which is invalid C#. Skip the cast in IsPossibleLossOfTypeInformation for null literals whenever the expected type contains an anonymous type: null is implicitly convertible to any reference type, so no cast is needed, and the anonymous type has no nameable form to cast to anyway. Fixes #3751
1 parent ddbb24f commit 9e281c5

3 files changed

Lines changed: 35 additions & 1 deletion

File tree

ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,12 @@ public async Task Issue3684([ValueSource(nameof(roslyn4OrNewerOptions))] Compile
936936
await RunForLibrary(cscOptions: cscOptions);
937937
}
938938

939+
[Test]
940+
public async Task Issue3751([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
941+
{
942+
await RunForLibrary(cscOptions: cscOptions);
943+
}
944+
939945
async Task RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, Action<DecompilerSettings> configureDecompiler = null)
940946
{
941947
await Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, configureDecompiler);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
3+
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
4+
{
5+
internal class Issue3751
6+
{
7+
private static bool Cond;
8+
9+
private static T Infer<T>(Func<T> factory)
10+
{
11+
return factory();
12+
}
13+
14+
public object Trigger()
15+
{
16+
return Infer(delegate {
17+
if (Cond)
18+
{
19+
Console.WriteLine();
20+
return null;
21+
}
22+
return new {
23+
Value = 1
24+
};
25+
});
26+
}
27+
}
28+
}

ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ private bool IsPossibleLossOfTypeInformation(IType givenType, IType expectedType
412412
if (expectedType == SpecialType.Dynamic)
413413
return true;
414414
if (givenType == SpecialType.NullType)
415-
return true;
415+
return !expectedType.ContainsAnonymousType();
416416
return false;
417417
}
418418

0 commit comments

Comments
 (0)