Skip to content

F# 6 takes fewer tailcalls in debug code when explicit /tailcalls+ is specified #12413

@dsyme

Description

@dsyme

This is an interesting problem I saw when investigating #12322

Context: Debug mode has "/tailcalls-" by default. However, users can turn on "/tailcalls+" explicitly for debug code, in which case we do expect tailcalls to be taken.

Now, for F# 6, fewer tailcalls are taken for Debug code "/tailcalls+". Consider the following continuation calling code:

    let g x cont = (x+2) |> cont
  • In F# 5 with "/tailcalls+", the "|> cont" was a tailcall
  • In F# 6 with "/tailcalls+", the "|> cont" is not a tailcall, I presume because of pipeline debugging on by default

Does this matter? I guess it does since Debug code now takes fewer tailcalls even when /tailcalls+ is specified.

Possible solutions

  • We could disable pipeline debugging for pipelines in tailcall-position when "/tailcalls+" is specified, or
  • We could completely disable pipeline debugging when "/tailcalls+" is specified.

The first is a little more work.

Symptom

Stack overflow in debug code when using F# 6 where it doesn't occur when using F# 5.

Workarounds

As workaround, you can enable optimizations in debug code which has "/tailcalls+" enabled. This suppresses pipeline debugging. However it makes debugging much worse.

Context

As context: I saw an instance of this in FSharp.Data when activating "/tailcalls+" in a design-time type provider - the overall projects compiled with F# 5 toolchain but didn't with F# 6 toolchain. However this only affected Debug code, including the Debug instance of the type provider. Turning optimizations on for the design-time type provider code would have disabled pipeline debugging and the tailcalls would ahve been recovered.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugImpact-High(Internal MS Team use only) Describes an issue with extreme impact on existing code.ReadyRegression

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions