Optimisation failure with structs in referenced projects
- Dominant language
- F#
- Stars
- 4.3k
- Forks
- 876
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 131
Description
Structs referenced from other projects have a significant optimisation failure whereby an instance of the struct cannot be passed to functions - it is always re-instantiated to empty just before the function call.
#### Repro steps
Imagine you have the following C# project with a single file:
```c#
namespace ClassLibrary1
{
public struct SomeStruct
{
private string _value;
public string Value => _value;
public void Set(string value)
{
_value = value;
}
}
}
```
The above project is referenced from F#:
```f#
open ClassLibrary1
let someFunc (s : SomeStruct) =
printfn "From inner: %A" s.Value
[]
let main argv =
let s = SomeStruct()
s.Set("there")
printfn "Pre call: %A" s.Value
someFunc s
printfn "Post call: %A" s.Value
0
```
#### Expected behavior
Output of the program is:
```
Pre call: "there"
From inner: "there"
Post call: "there"
```
#### Actual behavior
**With optimisations enabled (e.g. Release mode)**, the output is:
```
Pre call: "there"
From inner:
Post call: "there"
```
#### Known workarounds
No known workaround.
#### Related information
Severe bug, stopping me from using a C# library that uses structs.
The IL for the main function looks like:
```msil
.method public static int32 main(string[] argv) cil managed
{
.entrypoint
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.EntryPointAttribute::.ctor() = ( 01 00 00 00 )
// Code size 40 (0x28)
.maxstack 4
.locals init ([0] valuetype [ClassLibrary1]ClassLibrary1.SomeStruct s,
[1] valuetype [ClassLibrary1]ClassLibrary1.SomeStruct V_1)
IL_0000: nop
IL_0001: ldloca.s V_1
IL_0003: initobj [ClassLibrary1]ClassLibrary1.SomeStruct
IL_0009: ldloc.1
IL_000a: stloc.0
IL_000b: ldloca.s s
IL_000d: ldstr "there"
IL_0012: call instance void [ClassLibrary1]ClassLibrary1.SomeStruct::Set(string)
IL_0017: ldloca.s V_1 // WHY IS THIS HERE?
IL_0019: initobj [ClassLibrary1]ClassLibrary1.SomeStruct // WHY IS THIS HERE?
IL_001f: ldloc.1
IL_0020: call void Program::someFunc(valuetype [ClassLibrary1]ClassLibrary1.SomeStruct)
IL_0025: nop
IL_0026: ldc.i4.0
IL_0027: ret
} // end of method Program::main
```
IL_0017 and IL_0019 have been added by the optimiser - in Debug mode these instructions are not here, and the bad behaviour is not present.
Thanks
Contributor guide
Assessment
This issue has not been assessed yet.