Skip to content

Don't emit unnecessary closures #11898

@jl0pd

Description

@jl0pd

Compiler generates method closure when that's unneeded.

Repro steps

Compile and run code

let handler (x: string) (y: int) =
    System.Console.WriteLine(x, y)

let invokeHandler (foo: System.Action<string, int>) =
    for parameter in foo.Method.GetParameters() do
        printf "%s " parameter.Name

let problematicMethod () =
    invokeHandler (System.Action<_,_>(handler))

[<EntryPoint>]
let main argv =
    problematicMethod()
    0 

Expected behavior

x y is written to console

Actual behavior

delegateArg0 delegateArg1 is written.

Compiler wraps method with static class and calls Invoke method from it. Looks like someone has optimised this scenario, but it would be better if compiler wont generate static class at all. Current behavior increases assembly size, causes unnecessary call and most important - mangles names, which causes bugs

internal static class problematicMethod@9
{
    internal static void Invoke(string delegateArg0, int delegateArg1)
    {
        Console.WriteLine(delegateArg0, delegateArg1); // small methods gets inlined
        // big methods aren't inlined
        // handler.Invoke(delegateArg0, delegateArg1);
    }
}

Known workarounds

Use anonymous function with explicit argument names

let fixedMethod () =
    invokeHandler (System.Action<_,_>(fun x y -> handler x y))

Related information

Windows 10, net5 .NET SDK (reflecting any global.json): Version: 5.0.302 Commit: c005824e35

Runtime Environment:
OS Name: Windows
OS Version: 10.0.19043
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\5.0.302\

Host (useful for support):
Version: 5.0.8
Commit: 35964c9215

.NET SDKs installed:
3.1.411 [C:\Program Files\dotnet\sdk]
5.0.301 [C:\Program Files\dotnet\sdk]
5.0.302 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions