Stack trace skipping functions

Viewed 130

I'm looking at stack traces generated in F#, and they are skipping functions. A test case:

let foo() =
    failwithf "foo"

[<EntryPoint>]
let main argv =
    foo()
    0

Compiled with debug info, and run:

(torch) C:\t>fsc -g test.fs
Microsoft (R) F# Compiler version 10.8.0.0 for F# 4.7
Copyright (c) Microsoft Corporation. All Rights Reserved.

(torch) C:\t>test

Unhandled Exception: System.Exception: foo
   at Microsoft.FSharp.Core.PrintfModule.PrintFormatToStringThenFail@1637.Invoke(String message)
   at Test.main(String[] argv) in C:\t\test.fs:line 7

It says the exception was generated from main, with no mention of foo where it was actually generated.

How do I get the full stack trace, including the function that actually generated the exception?

1 Answers

You have been the victim of optimizations, which make debugging difficult in any toolchain.

Please note that for fsc, optimizations are turned on by default. They are:

Inlining

foo() isn't even called - it's a simple static method, which can be easily inlined. The resulting IL is equivalent to:

let main argv =
    PrintfModule.PrintFormatToStringThenFail(new PrintfFormat<_>("foo"));
    0

We can turn this off with --optimize-

fsc -g --optimize- Program.fs

But this still isn't enough. Because of...

Tail-call optimization

A tail-call optimization lets you avoid allocating a new stack frame for a function. foo is a simple function which shorts main. And since there's no stack frame, you don't see it in the stack trace.

We can turn this off with --tailcalls-.

For the full debugging experience, go with what VS basically does for DEBUG:

fsc --debug:full --define:DEBUG --define:TRACE --optimize- --tailcalls- Program.fs

Now if we run our target, we get the stacktrace as expected:

Unhandled Exception: System.Exception: foo
   at Microsoft.FSharp.Core.PrintfModule.PrintFormatToStringThenFail@1639.Invoke(String message)
   at Program.foo[a]() in Program.fs:line 4
   at Program.main(String[] argv) in Program.fs:line 13
Related