dotnet / dotnet/fsharp

Stack overflow typechecking large CEs on macOS

Open
#13,084 8 comments 0 reactions 0 assignees View on GitHub
Area-Compiler-Checking Bug Impact-Medium
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 11h
Merged PRs (30d)
131

Description

Upgrading from FSAC v0.51.0 to v0.52.0 (Ionide 6.0.0) triggers a stack overflow in `FSharp.Compiler.CheckComputationExpressions` on macOS when attempting to typecheck a file containing large CEs.

I saw similar issues a couple of years ago with early versions of the netcore FSAC. Tracing through the versions, it looks like there may have been a performance regression between FCS 41.0.1 and 41.0.3?

**Repro steps**

Open the following file on macOS
```
#r "nuget: Chiron"

open Chiron

type LargeRecord =
{
Property1: string
Property2: string
Property3: string
Property4: string
Property5: string
Property6: string
Property7: string
Property8: string
Property9: string
Property10: string
Property11: string
Property12: string
Property13: string
Property14: string
Property15: string
Property16: string
Property17: string
Property18: string
Property19: string
Property20: string
Property21: string
Property22: string
Property23: string
Property24: string
Property25: string
Property26: string
Property27: string
Property28: string
Property29: string
Property30: string
Property31: string
Property32: string
Property33: string
Property34: string
Property35: string
Property36: string
Property37: string
}
with
static member ToJson(x: LargeRecord) = json {
do! Json.write "property1" x.Property1
do! Json.write "property2" x.Property2
do! Json.write "property3" x.Property3
do! Json.write "property4" x.Property4
do! Json.write "property5" x.Property5
do! Json.write "property6" x.Property6
do! Json.write "property7" x.Property7
do! Json.write "property8" x.Property8
do! Json.write "property9" x.Property9
do! Json.write "property10" x.Property10
do! Json.write "property11" x.Property11
do! Json.write "property12" x.Property12
do! Json.write "property13" x.Property13
do! Json.write "property14" x.Property14
do! Json.write "property15" x.Property15
do! Json.write "property16" x.Property16
do! Json.write "property17" x.Property17
do! Json.write "property18" x.Property18
do! Json.write "property19" x.Property19
do! Json.write "property20" x.Property20
do! Json.write "property21" x.Property21
do! Json.write "property22" x.Property22
do! Json.write "property23" x.Property23
do! Json.write "property24" x.Property24
do! Json.write "property25" x.Property25
do! Json.write "property26" x.Property26
do! Json.write "property27" x.Property27
do! Json.write "property28" x.Property28
do! Json.write "property29" x.Property29
do! Json.write "property30" x.Property30
do! Json.write "property31" x.Property31
do! Json.write "property32" x.Property32
do! Json.write "property33" x.Property33
do! Json.write "property34" x.Property34
do! Json.write "property35" x.Property35
do! Json.write "property36" x.Property36
do! Json.write "property37" x.Property37
}
```

**Expected behavior**

File typechecks successfully

**Actual behavior**

Language server crashes and reports a stack overflow starting with:

```
Stack overflow.
at FSharp.Compiler.Syntax.DebugPointAtLeafExpr.NewYes(FSharp.Compiler.Text.Range)
at FSharp.Compiler.CheckComputationExpressions.convertSimpleReturnToExpr@1668(TcFileState, UnscopedTyparEnv, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, TType, AccessorDomain, System.String, Boolean, Microsoft.FSharp.Collections.FSharpList`1, System.Collections.Generic.IDictionary`2,MethInfo>>>>, System.Collections.Generic.IDictionary`2,MethInfo>>>>, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, TcEnv, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, Boolean, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, FSharp.Compiler.Syntax.SynExpr)
at FSharp.Compiler.CheckComputationExpressions.transBind@1630(TcFileState, UnscopedTyparEnv, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, TType, AccessorDomain, System.String, Boolean, Microsoft.FSharp.Collections.FSharpList`1, System.Collections.Generic.IDictionary`2,MethInfo>>>>, System.Collections.Generic.IDictionary`2,MethInfo>>>>, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, TcEnv, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, Boolean, CustomOperationsMode, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, FSharp.Compiler.Text.Range, Microsoft.FSharp.Core.FSharpFunc`2, System.String, Microsoft.FSharp.Collections.FSharpList`1, FSharp.Compiler.Syntax.SynPat, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions+tryTrans@776-1.Invoke(Microsoft.FSharp.Core.Unit)
at FSharp.Compiler.ErrorLogger+StackGuard.Guard[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions.tryTrans@774(TcFileState, UnscopedTyparEnv, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, TType, AccessorDomain, System.String, Boolean, Microsoft.FSharp.Collections.FSharpList`1, System.Collections.Generic.IDictionary`2,MethInfo>>>>, System.Collections.Generic.IDictionary`2,MethInfo>>>>, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, TcEnv, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, Boolean, CompExprTranslationPass, CustomOperationsMode, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions.trans@1589-2(TcFileState, UnscopedTyparEnv, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, TType, AccessorDomain, System.String, Boolean, Microsoft.FSharp.Collections.FSharpList`1, System.Collections.Generic.IDictionary`2,MethInfo>>>>, System.Collections.Generic.IDictionary`2,MethInfo>>>>, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, TcEnv, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, Boolean, CompExprTranslationPass, CustomOperationsMode, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions.transBind@1630(TcFileState, UnscopedTyparEnv, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, TType, AccessorDomain, System.String, Boolean, Microsoft.FSharp.Collections.FSharpList`1, System.Collections.Generic.IDictionary`2,MethInfo>>>>, System.Collections.Generic.IDictionary`2,MethInfo>>>>, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, TcEnv, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, Boolean, CustomOperationsMode, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, FSharp.Compiler.Text.Range, Microsoft.FSharp.Core.FSharpFunc`2, System.String, Microsoft.FSharp.Collections.FSharpList`1, FSharp.Compiler.Syntax.SynPat, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions+tryTrans@776-1.Invoke(Microsoft.FSharp.Core.Unit)
at FSharp.Compiler.ErrorLogger+StackGuard.Guard[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions.tryTrans@774(TcFileState, UnscopedTyparEnv, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, TType, AccessorDomain, System.String, Boolean, Microsoft.FSharp.Collections.FSharpList`1, System.Collections.Generic.IDictionary`2,MethInfo>>>>, System.Collections.Generic.IDictionary`2,MethInfo>>>>, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, TcEnv, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, Boolean, CompExprTranslationPass, CustomOperationsMode, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions.trans@1589-2(TcFileState, UnscopedTyparEnv, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, TType, AccessorDomain, System.String, Boolean, Microsoft.FSharp.Collections.FSharpList`1, System.Collections.Generic.IDictionary`2,MethInfo>>>>, System.Collections.Generic.IDictionary`2,MethInfo>>>>, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, TcEnv, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, Boolean, CompExprTranslationPass, CustomOperationsMode, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions+tryTrans@776-1.Invoke(Microsoft.FSharp.Core.Unit)
at FSharp.Compiler.ErrorLogger+StackGuard.Guard[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions.tryTrans@774(TcFileState, UnscopedTyparEnv, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, TType, AccessorDomain, System.String, Boolean, Microsoft.FSharp.Collections.FSharpList`1, System.Collections.Generic.IDictionary`2,MethInfo>>>>, System.Collections.Generic.IDictionary`2,MethInfo>>>>, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, TcEnv, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, Boolean, CompExprTranslationPass, CustomOperationsMode, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions.trans@1589-2(TcFileState, UnscopedTyparEnv, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, TType, AccessorDomain, System.String, Boolean, Microsoft.FSharp.Collections.FSharpList`1, System.Collections.Generic.IDictionary`2,MethInfo>>>>, System.Collections.Generic.IDictionary`2,MethInfo>>>>, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, TcEnv, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, Boolean, CompExprTranslationPass, CustomOperationsMode, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions.transBind@1630(TcFileState, UnscopedTyparEnv, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, TType, AccessorDomain, System.String, Boolean, Microsoft.FSharp.Collections.FSharpList`1, System.Collections.Generic.IDictionary`2,MethInfo>>>>, System.Collections.Generic.IDictionary`2,MethInfo>>>>, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, TcEnv, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, Boolean, CustomOperationsMode, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, FSharp.Compiler.Text.Range, Microsoft.FSharp.Core.FSharpFunc`2, System.String, Microsoft.FSharp.Collections.FSharpList`1, FSharp.Compiler.Syntax.SynPat, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions+tryTrans@776-1.Invoke(Microsoft.FSharp.Core.Unit)
at FSharp.Compiler.ErrorLogger+StackGuard.Guard[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions.tryTrans@774(TcFileState, UnscopedTyparEnv, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, TType, AccessorDomain, System.String, Boolean, Microsoft.FSharp.Collections.FSharpList`1, System.Collections.Generic.IDictionary`2,MethInfo>>>>, System.Collections.Generic.IDictionary`2,MethInfo>>>>, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, TcEnv, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, Boolean, CompExprTranslationPass, CustomOperationsMode, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions.trans@1589-2(TcFileState, UnscopedTyparEnv, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, TType, AccessorDomain, System.String, Boolean, Microsoft.FSharp.Collections.FSharpList`1, System.Collections.Generic.IDictionary`2,MethInfo>>>>, System.Collections.Generic.IDictionary`2,MethInfo>>>>, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, Microsoft.FSharp.Core.FSharpFunc`2, TcEnv, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, Boolean, CompExprTranslationPass, CustomOperationsMode, Internal.Utilities.Library.LazyWithContext`2,TcEnv>,FSharp.Compiler.Text.Range>, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpFunc`2)
at FSharp.Compiler.CheckComputationExpressions+tryTrans@776-1.Invoke(Microsoft.FSharp.Core.Unit)
```

**Known workarounds**

Setting the environment variable `COMPlus_DefaultStackSize=180000` allows typecheck to complete successfully

**Related information**

* Operating system: macOS 12.3.1 on an M1 machine; I've also reproduced on macOS x86_64 although I needed about 10 more `do!` expressions
* .NET Runtime: 6.0.201 (arm64 version)

```
.NET SDK (reflecting any global.json):
Version: 6.0.201
Commit: ef40e6aa06

Runtime Environment:
OS Name: Mac OS X
OS Version: 12.3
OS Platform: Darwin
RID: osx.12-arm64
Base Path: /usr/local/share/dotnet/sdk/6.0.201/

Host (useful for support):
Version: 6.0.3
Commit: c24d9a9c91

.NET SDKs installed:
6.0.201 [/usr/local/share/dotnet/sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.3 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.3 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
```
* Editing Tools: VS Code 1.66.2 with Ionide 6.0.3

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.