Fsharp: breakpoints doesnt work with anonymous records in .net core sdk

Created on 12 Apr 2019  路  36Comments  路  Source: dotnet/fsharp

Setting breakpoint if the code contains anonymous records, doesnt work

I not yet tried in VS, but with latest .net core debugger and latest .net core sdks affect vscode
Ionide doesnt matter, the debugger is in MS code and i am using the VSCode Debug tab with tasks.json and launch.json

Repro steps

create a simple program with dotnet new console -lang f#

[<EntryPoint>]
let main argv =
    printfn "Hello World from F#!"

    // let a = {| A = 1 |}

    printfn "A"

    // printfn "%A" a

    0 // return an integer exit code

and set some breakpoint at the instructions.
Running in debug, it stop on breakpoint and debug works

if i uncomment the lines, the debugger doesnt stop on any breakpoint (not just anon records)

if i set debugger to stop at entry point, it stop an entry and i can step by step, but breakpoint are not enabled

image

the debug info show it cannot bind the line to breakpoint

Breakpoint warning: No executable code of the debugger鈥檚 target code type is associated with this line.
Possible causes include: conditional compilation, compiler optimizations, or the target architecture of this line is not supported by the current debugger code type. - e:\temp\pwa\Program.fs:6

Expected behavior

breakpoints works

Actual behavior

breakpoints doesnt works

Known workarounds

stop at entry point maybe, in vscode is done at launch.json

            "stopAtEntry": true,

Related information

can repro in .NET Core 2.1.603 and 3.0.100-preview3-010431

.NET Core SDK (reflecting any global.json):
 Version:   2.1.603
 Commit:    ae71c68742

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.17134
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.1.603\

Host (useful for support):
  Version: 3.0.0-preview3-27503-5
  Commit:  3844df9537

.NET Core SDKs installed:
  2.1.603 [C:\Program Files\dotnet\sdk]
  3.0.100-preview3-010431 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:

  Microsoft.NETCore.App 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.0-preview3-27503-5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.0.0-preview3-27504-2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

C# VSCode extension (who contains the debugger stuff)

Name: C#
Id: ms-vscode.csharp
Description: C# for Visual Studio Code (powered by OmniSharp).
Version: 1.18.0
Publisher: Microsoft
VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp
Area-Compiler bug

Most helpful comment

@renato04 this will be in the compiler that corresponds to the VS 16.3 update. If you use the previews, it should already be in.

All 36 comments

/cc @Krzysztof-Cieslak FYI , because affect anon record debugging in vscode
/cc @auduchinok FYI, because affect Rider

I can also reproduce this on Windows 10 with .NET Core 2.2.202, using both VSCode (with Ionide and Omnisharp) and Rider.

.NET Core SDK (reflecting any global.json):
 Version:   2.2.202
 Commit:    8a7ff6789d

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.17763
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.2.202\

Host (useful for support):
  Version: 2.2.3
  Commit:  6b8ad509b6

.NET Core SDKs installed:
  2.2.202 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download

Reproduced in VS as well. @dsyme @KevinRansom are we emitting the appropriate PDB info?

In VS any use of non-commented-out anonymous records breaks all ability to debug with breakpoints.

@cartermp, great issue, it needs to be looked at for sure.

@dsyme @KevinRansom @TIHan this one is rather severe. It's impossible for me to debug anything if I use anonymous records. Example:

open System

[<EntryPoint>]
let main argv =
    printfn "Hey"

    let data = {| X = 1; Y = "abc" |}
    let result = data.X + data.Y.Length
    let newData = {| data with Z = data.X + 5 |}

    0 // return an integer exit code

Set a breakpoint on each line in VS and observe that none are ever hit (not even the first printfn). If I uncomment each of the anonymous record lines, it first breakpoint is hit.

I will look at it early next week, or perhaps even over the weekend.

@KevinRansom have you had a chance to look at this one?

I checked ValidateBreakpointLocationImpl and it has an entry:

                  | SynExpr.AnonRecd (_isStruct, copyExprOpt, fs, _) ->
                      match copyExprOpt with
                      | Some (e, _) -> yield! walkExpr true e
                      | None -> ()
                      yield! walkExprs (fs |> List.map snd)

so not yet sure what the cause of this could be

@dsyme IIRC that member is called when setting the breakpoint, but I'm not sure if it's called when you're actually debugging.

It appears I'm still experiencing this issue after Visual Studio's 16.1.1 update with FSharp.Core 4.6.2, is there something else I need to update?

Thanks @lfr, this is not resolved.

@KevinRansom @brettfo @TIHan Much of what we slated for 16.1 was never pulled in, see here: https://github.com/dotnet/fsharp/commits/Visual-Studio-2019-Version-16.1?after=42526fe359672a05fd562dc16a91a43d0fe047a7+34

Is this problem fixed I still have unverified breakpoints in Vscode

@afshawnlotfi Yes, but the compiler with the fix has not be released yet.

Alright well for now I guess I'll just keep everything not anonymous and put a TODO to change it later

@afshawnlotfi , this will be shipped with VS2019.2.

It is currently in preview you can download the VS priview here: https://visualstudio.microsoft.com/vs/preview/?OCID=AID2318528_SEM_u43DwN0V&MarinID=u43DwN0V_79233641541298_visual%20studio%20preview_be_c__1267737265630647_kwd-79233812309844:loc-190_

What if I want to use it with Vscode. Would I have to wait for the new version of dotnet CLI

A dotnet cli ships with the preview, and it matches the vs compiler.

@KevinRansom @brettfo @TIHan This is still not resolved in the VS 16.2 Preview 4 builds.

Can the fix get flowed into a release branch before we release?

Looks like the fix is in the branch. But it doesn't resolve anything.

@cartermp THe debugging is working for me with a fresh build of the compiler from master and running as .NET Framework program

a.fs:

[<EntryPoint>]
let main argv =
    printfn "Hello World from F#!"

    let a = {| A = 1 |}

    printfn "%A" a

    0 // return an integer exit code

then

artifacts\bin\fsc\Debug\net472\fsc -g --optimize- a.fs
devenv /debugexe a.exe

I can set break point and hit it.

I'll check .NET Core separately I suppose.

As mentioned offline we need to test netcoreapp (where it failed) and against a release branch, since master is not what is shipping

I looked at this and can repro that there is still a major problem on .NET Core. It is really surprising to have two blocking issues on this debugging.

Something about the very existence of any anon-record types in the assembly seems to hork debugging on .NET Core. I'm going to keep digging into it, but I'm quite concerned as I believe it must be something in the C# debug engine which is somehow failing for these specific types. But what that could be and why that would interfere with breakpoints specifically I really don't understand.

I'll list repro instructions here tomorrow.

Tagging @tmat as well - we'll need to dig into this for sure.

OK, I've confirmed this is something to do with portable PDB generation. I'm not sure what it could be but it's definitely the issue

If a.fs contains a use of an anonymous record then with this I can't set breakpoints:

artifacts\bin\fsc\Debug\net472\fsc.exe --debug:portable --optimize- a.fs
devenv /debugexe a.exe

but with old-fashioned PDB I can set breakpoints:

artifacts\bin\fsc\Debug\net472\fsc.exe --debug:full --optimize- a.fs
devenv /debugexe a.exe

This might be one for you @KevinRansom, or at least how do we proceed fro here - is there a tool to debug dump the portable PDB file generated

It's very odd as there's nothing that unusual about the code generated. For the record, other things I've investigated today:

  • It doesn't matter if the code containing the anonymous record isn't actually executed, the breakpoints still aren't hit if any anon recd exists in the assembly, even if it's in a different file

  • It doesn't matter if the name of the generated anon recd class is changed to be qqf__AnonymousType709851358`1 instead of <>f__AnonymousType709851358`1

  • It doesn't matter if the name of the generic type parameter for the anon recd class is Aj__TPar instead of <A>j__TPar

So what remains is pretty "normal" code for a record type really. I'm not sure why we would be failing to generate a correct portable PDB just because an anonymous record class is generated too.

  • Any reason why we emit a generic class for an anonymous record?
  • Maybe this is some weird bug in the debugger where it doesn't like that there is no type definition (source code reference) for one of the types and completely fails in some init code? (or something similar)

There's been anonymous classes in C# for a while, don't F# anonymous records use the same mechanism underneath?

Is the debugger code itself open source? Can we somehow debug it? I couldn't find any useful documentation around that area (probably because Google fails me there). I assume it is because Omnisharp somehow seems to work on Ubuntu as well, or is that a false assumption? Maybe we can ping people who would know more?

There's been anonymous classes in C# for a while, don't F# anonymous records use the same mechanism underneath?

They do. We generate almost identical code. That's why this is so mysterious. Will try to dig into it again now.

Running pdb2xml on the portable PDB file seems to detect an error:

C:\GitHub\dsyme\visualfsharp>C:\Users\dsyme\Downloads\Pdb2Xml.1.1.0-roslyn-62714-01\tools\Pdb2Xml.exe a.exe
Invalid compressed integer.

I'll look into it more

@dsyme see here: https://github.com/dotnet/fsharp/issues/6728

Probably related issues then!

Is this seriously still a problem now. This was reported in April. Just saying if this were C# this would have been patched the first week.

Hello!
I'm facing the same problem using VS2019 Community 16.2.1 targeting .net Core 2.2 using FSharp.Core 4.6.2 or VS Code

If I try to debug the following code it does not hit on printfn line

open System

[<EntryPoint>]
let main argv =
    printfn "Hello World from F#!"

    let a = {| A = 1 |}

    printfn "%A" a

    0 // return an integer exit code

But when I try to debug this code It works very well

open System
type Test =
    {A: int}
[<EntryPoint>]
let main argv =
    printfn "Hello World from F#!"

    let a = { A = 1 }

    printfn "%A" a

    0 // return an integer exit code

Do I have to install or update something?

@renato04 this will be in the compiler that corresponds to the VS 16.3 update. If you use the previews, it should already be in.

@cartermp which .NET Core version works properly with F# anon records and debugger? Any 2.2.xxx?

Because of this I switched from 2.2.402 -> 3.0.100, however I am not able to migrate everything so quickly to 3.0, and wondering if there is any 2.2.xxx version which works properly ...

@deyanp it is in the 3.0.x SDK. .NET Core 2.2.x is now officially out of support, so I recommend switching to 3.0.x.

Was this page helpful?
0 / 5 - 0 ratings