fsharp
fsharp copied to clipboard
Variable in scope is not visible after a bang!-operation in CE
At least in the async CE, after a monadic operation (let!/do!/match! etc.), variables in the debugger suddenly seem to go out of scope:
module Program =
let f x =
async {
do! async.Return ()
return 1
}
[<EntryPoint>]
let main _argv =
f 0 |> Async.RunSynchronously |> printfn "%A"
0
(Screenshots from Rider. Originally reported there, but was redirected here.)
@cmeeren Do you know which compiler version was used? @dsyme was making some changes to how the compiler emits debug points some time ago, I wonder whether it already has those changes or no.
No idea. A repro solution was attached. You can try that.
@cmeeren You can look it up here:

MSBuild 17.0, SDK 6.0.300.
It's same in VS, I guess it's related to how we store (or rather what we store/not store) in LocalScope/LocalVariable tables, need to look at which scopes we generate.
Update: Generated PDB for the code above (fsc.exe --pdb:program.pdb --optimize- --debug:portable .\program.fs
):
<?xml version="1.0" encoding="utf-8"?>
<Pdb Name="program" Path="C:\Users\vlza\code\fsharp\artifacts\bin\fsc\Release\net472\program.pdb" AssemblyPath="C:\Users\vlza\code\fsharp\artifacts\bin\fsc\Release\net472\program.exe" PdbType="Portable" Signature="aadce3f8-84a8-479d-8642-914fc6bcafa9" TimeDateStamp="A88B2C46" AgeOrTimestampFromAssembly="A88B2C46 " SignatureFromAssembly="aadce3f8-84a8-479d-8642-914fc6bcafa9 " PdbFileFromAssembly="C:\Users\vlza\code\fsharp\artifacts\bin\fsc\Release\net472\program.pdb ">
<UserEntryPoint>6000002</UserEntryPoint>
<Document Index="1" DocumentType="Text" Language="F#" LanguageVendor="Microsoft" ChecksumAlgorithm="SHA-256" Checksum="f8 86 43 6d f1 a9 3f 23 43 2b 48 c5 61 27 ca 36 5f 43 99 7c 9e a0 dd 34 48 a3 60 58 06 3f b7 9f ">C:\Users\vlza\code\fsharp\artifacts\bin\fsc\Release\net472\program.fs</Document>
<ImportScope Index="1" Parent="null" />
<ImportScope Index="2" Parent="1">
<Import>Microsoft</Import>
<Import>Microsoft.FSharp</Import>
<Import>ImportType(0100000E ) </Import>
<Import>Microsoft.FSharp.Core</Import>
<Import>Microsoft.FSharp.Collections</Import>
<Import>Microsoft.FSharp.Control</Import>
<Import>ImportType(0100000F ) </Import>
<Import>ImportType(01000010 ) </Import>
<Import>ImportType(01000011 ) </Import>
<Import>ImportType(01000012 ) </Import>
<Import>ImportType(01000013 ) </Import>
</ImportScope>
<Method Token="6000001" LocalVariablesSignatureToken="11000002">
<SequencePoints DocumentIndex="1">
<SequencePoint IlOffset="IL_0000" StartLine="4" StartColumn="5" EndLine="4" EndColumn="10" />
</SequencePoints>
<Scope OffsetRange="IL_0000-IL_0015" IsRoot="True" Method="6000001" ImportScope="2" />
</Method>
<Method Token="6000002" LocalVariablesSignatureToken="11000006">
<SequencePoints DocumentIndex="1">
<SequencePoint IlOffset="IL_0000" StartLine="11" StartColumn="5" EndLine="11" EndColumn="8" />
<SequencePoint IlOffset="IL_0007" StartLine="11" StartColumn="12" EndLine="11" EndColumn="34" />
<SequencePoint IlOffset="IL_0012" StartLine="11" StartColumn="38" EndLine="11" EndColumn="50" />
<SequencePoint IlOffset="IL_002e" StartLine="12" StartColumn="5" EndLine="12" EndColumn="6" />
</SequencePoints>
<Scope OffsetRange="IL_0000-IL_0030" IsRoot="True" Method="6000002" ImportScope="2">
<Scope OffsetRange="IL_0006-IL_002e" IsRoot="False" Method="6000002" ImportScope="2">
<LocalVariable LocalVariablesSignatureToken="11000006" IlIndex="0" Attributes="None">Pipe #1 input at line 11</LocalVariable>
<Scope OffsetRange="IL_0011-IL_002e" IsRoot="False" Method="6000002" ImportScope="2">
<LocalVariable LocalVariablesSignatureToken="11000006" IlIndex="1" Attributes="None">Pipe #1 stage #1 at line 11</LocalVariable>
</Scope>
</Scope>
</Scope>
</Method>
<Method Token="6000003">
<Scope OffsetRange="IL_0000-IL_0007" IsRoot="True" Method="6000003" ImportScope="2" />
</Method>
<Method Token="6000004">
<Scope OffsetRange="IL_0000-IL_000a" IsRoot="True" Method="6000004" ImportScope="2" />
</Method>
<Method Token="6000005">
<Scope OffsetRange="IL_0000-IL_000b" IsRoot="True" Method="6000005" />
</Method>
<Method Token="6000006">
<Scope OffsetRange="IL_0000-IL_000e" IsRoot="True" Method="6000006" ImportScope="2" />
</Method>
<Method Token="6000007">
<Scope OffsetRange="IL_0000-IL_000f" IsRoot="True" Method="6000007" ImportScope="2" />
</Method>
<Method Token="6000008">
<Scope OffsetRange="IL_0000-IL_000e" IsRoot="True" Method="6000008" ImportScope="2" />
</Method>
<Method Token="6000009" LocalVariablesSignatureToken="11000007">
<SequencePoints DocumentIndex="1">
<SequencePoint IlOffset="IL_0000" Hidden="true" />
<SequencePoint IlOffset="IL_0002" StartLine="6" StartColumn="7" EndLine="6" EndColumn="15" />
</SequencePoints>
<Scope OffsetRange="IL_0000-IL_0019" IsRoot="True" Method="6000009" ImportScope="2" />
</Method>
<Method Token="600000A">
<Scope OffsetRange="IL_0000-IL_0015" IsRoot="True" Method="600000A" ImportScope="2" />
</Method>
<Method Token="600000B">
<Scope OffsetRange="IL_0000-IL_0015" IsRoot="True" Method="600000B" ImportScope="2" />
</Method>
<Method Token="600000C">
<Scope OffsetRange="IL_0000-IL_000e" IsRoot="True" Method="600000C" ImportScope="2" />
</Method>
<Method Token="600000D" LocalVariablesSignatureToken="1100000A">
<SequencePoints DocumentIndex="1">
<SequencePoint IlOffset="IL_0000" StartLine="5" StartColumn="7" EndLine="5" EndColumn="26" />
</SequencePoints>
<Scope OffsetRange="IL_0000-IL_0033" IsRoot="True" Method="600000D" ImportScope="2" />
</Method>
<Type Name="Program">
<File>C:\Users\vlza\code\fsharp\artifacts\bin\fsc\Release\net472\program.fs</File>
</Type>
<Type Name="Program+Program">
<File>C:\Users\vlza\code\fsharp\artifacts\bin\fsc\Release\net472\program.fs</File>
</Type>
<Type Name="Program+Program+f@5">
<File>C:\Users\vlza\code\fsharp\artifacts\bin\fsc\Release\net472\program.fs</File>
</Type>
<Type Name="Program+Program+f@6-2">
<File>C:\Users\vlza\code\fsharp\artifacts\bin\fsc\Release\net472\program.fs</File>
</Type>
</Pdb>```
Any chance to have a look at this? It's making debugging rather cumbersome, since I have to insert spurious code everywhere just to be able to break on and inspect the variables I'm after.
I agree the situation is not ideal, but if the variable is captured, you will see it under this
or you can move up the stack a little bit.
There is nothing under this
, and nothing further up the stack. Actually no user code at all further up in the stack.
It's the same in VS:
Ah, you're right. Tasks seem to be better in this regard
As a side note, I can mention that stack traces involving Async
quite often seem to contain minimal user code, or even none at all, making it impossible based on a logged stack trace to see where something went wrong. Not sure if it's related or a separate issue, but that's always been a major issue for me with F#.
Any chance to have a look at this? It's making debugging rather cumbersome, since I have to insert spurious code everywhere just to be able to break on and inspect the variables I'm after.
It's not as trivial unfortunately, and will likely require some substantial changes. We'll see when we can plan it.