Skip to content

Compiling causes OutOfMemoryException and IDE unresponsive/crash when pattern matching against record with many nested DU fields #4691

Open
@cmeeren

Description

@cmeeren

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

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.

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:
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 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions