Implicit boxing produces extraneous closure
- Dominant language
- F#
- Stars
- 4.3k
- Forks
- 876
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 131
Description
**Repro steps**
Minimized repro ([sharplab](https://sharplab.io/#v2:DYLgZgzgPgtg9gEwK7AKYAIBic4FgBQBaALumDugBRwBGI6tAVgJToC86NcAHpWEgDsqrALQA+BjQB0AFTgBlYgCcAlgIDmlZqxAB+CZUErS49BGVr1zAkVSl1cLezIUARAAsVrgkA==)):
```fsharp
module Foo
let foo (ob: obj) = box(fun () -> ob.ToString()) :?> (unit -> string)
let go() = foo "hi"
```
**Expected behavior**
A single closure should be allocated.
**Actual behavior**
A second, extraneous closure is allocated that simply wraps the first. Here is the decompiled C# for that closure from sharplab:
```csharp
[Serializable]
internal sealed class go@5 : FSharpFunc
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
public FSharpFunc clo1;
[CompilerGenerated]
[DebuggerNonUserCode]
internal go@5(FSharpFunc clo1)
{
this.clo1 = clo1;
}
public override string Invoke(Unit arg10)
{
return clo1.Invoke(arg10);
}
}
```
**Known workarounds**
Explicitly boxing the argument doesn't produce the extra closure ([sharplab](https://sharplab.io/#v2:DYLgZgzgPgtg9gEwK7AKYAIBic4FgBQBaALumDugBRwBGI6tAVgJToC86NcAHpWEgDsqrALQA+BjQB0AFTgBlYgCcAlgIDmlZqxAB+CZUErS49BGVr1zAkVSl1cLezI5KXbugBEACxWfmQA=)):
```fsharp
module Foo
let foo (ob: obj) = box(fun () -> ob.ToString()) :?> (unit -> string)
let go() = foo(box "hi")
```
**Related information**
Provide any related information (optional):
* Operating system
* .NET Runtime kind (.NET Core, .NET Framework, Mono)
* Editing Tools (e.g. Visual Studio Version, Visual Studio)
Contributor guide
Assessment
This issue has not been assessed yet.