Compiling causes OutOfMemoryException and IDE unresponsive/crash when pattern matching against record with many nested DU fields
- Dominant language
- F#
- Stars
- 4.3k
- Forks
- 876
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 131
Description
I expecience OutOfMemoryException when compiling code that pattern matches many cases on a record with many fields that are nested DU (e.g. `int option option` as shown in the repro below, but I originally experienced it with other DU types). Furthermore, the IDE/Intellisense becomes unresponsive and may crash.
#### Repro steps
[Test.zip](https://github.com/Microsoft/visualfsharp/files/1882852/Test.zip)
Either try the test solution, or simply create a new .NET Standard library (others may produce the error too, but I haven't tested), paste the following code and compile/observe IDE behavior.
```f#
module Test
type ManyFields =
{
Field1: int option option
Field2: int option option
Field3: int option option
Field4: int option option
Field5: int option option
Field6: int option option
Field7: int option option
Field8: int option option
Field9: int option option
Field10: int option option
Field11: int option option
Field12: int option option
Field13: int option option
Field14: int option option
Field15: int option option
Field16: int option option
Field17: int option option
Field18: int option option
Field19: int option option
Field20: int option option
}
let getFirstField manyFields =
match manyFields with
| { Field1 = Some (Some i) } -> Some i
| { Field2 = Some (Some i) } -> Some i
| { Field3 = Some (Some i) } -> Some i
| { Field4 = Some (Some i) } -> Some i
| { Field5 = Some (Some i) } -> Some i
| { Field6 = Some (Some i) } -> Some i
| { Field7 = Some (Some i) } -> Some i
| { Field8 = Some (Some i) } -> Some i
| { Field9 = Some (Some i) } -> Some i
| { Field10 = Some (Some i) } -> Some i
| { Field11 = Some (Some i) } -> Some i
| { Field12 = Some (Some i) } -> Some i
| { Field13 = Some (Some i) } -> Some i
| { Field14 = Some (Some i) } -> Some i
| { Field15 = Some (Some i) } -> Some i
| { Field16 = Some (Some i) } -> Some i
| { Field17 = Some (Some i) } -> Some i
| { Field18 = Some (Some i) } -> Some i
| { Field19 = Some (Some i) } -> Some i
| { Field20 = Some (Some i) } -> Some i
| _ -> None
```
#### Expected behavior
The code compiles successfully.
#### Actual behavior
Compilation fails with the following output (the number of exceptions may vary):
```
1>------ Rebuild All started: Project: Test, Configuration: Debug Any CPU ------
1>error FS0193 : internal error : Exception of type 'System.OutOfMemoryException' was thrown.
1>error FS0193 : internal error : Exception of type 'System.OutOfMemoryException' was thrown.
1>Done building project "Test.fsproj" -- FAILED.
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
```
#### Known workarounds
* Break up the pattern matching if possible. On my machine it seems that 18 cases are fine, but 19+ will cause the error. For example, the following works fine:
```f#
let getFirstField manyFields =
match manyFields with
| { Field1 = Some (Some i) } -> Some i
| { Field2 = Some (Some i) } -> Some i
| { Field3 = Some (Some i) } -> Some i
| { Field4 = Some (Some i) } -> Some i
| { Field5 = Some (Some i) } -> Some i
| { Field6 = Some (Some i) } -> Some i
| { Field7 = Some (Some i) } -> Some i
| { Field8 = Some (Some i) } -> Some i
| { Field9 = Some (Some i) } -> Some i
| { Field10 = Some (Some i) } -> Some i
| _ -> match manyFields with
| { Field11 = Some (Some i) } -> Some i
| { Field12 = Some (Some i) } -> Some i
| { Field13 = Some (Some i) } -> Some i
| { Field14 = Some (Some i) } -> Some i
| { Field15 = Some (Some i) } -> Some i
| { Field16 = Some (Some i) } -> Some i
| { Field17 = Some (Some i) } -> Some i
| { Field18 = Some (Some i) } -> Some i
| { Field19 = Some (Some i) } -> Some i
| { Field20 = Some (Some i) } -> Some i
| _ -> None
```
* Find a completely different way to do control flow
* Find a different way to design your code
#### Related information
[This SO answer](https://stackoverflow.com/a/10618544/2978652) by Tomas Petricek looks relevant. If it's the same underlying problem, then it has been around since at least 2012. About time it's fixed :)
Versions:
* VS 15.6.5
* VF# Tools 10.1 for F# 4.1 - 15.6.0.0
Contributor guide
Assessment
This issue has not been assessed yet.