Bug 21537 - When using F# Tupled functions dont have correct debug display or locals
Summary: When using F# Tupled functions dont have correct debug display or locals
Alias: None
Product: Compilers
Classification: Mono
Component: Other ()
Version: unspecified
Hardware: Macintosh Mac OS
: Normal normal
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2014-07-23 04:38 UTC by Dave Thomas
Modified: 2015-01-14 03:34 UTC (History)
4 users (show)

Is this bug a regression?: ---
Last known good build:

Screenshot showing 'one' (77.42 KB, image/png)
2014-07-23 04:38 UTC, Dave Thomas
Screen shot showing 'two' (79.45 KB, image/png)
2014-07-23 04:38 UTC, Dave Thomas

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Dave Thomas 2014-07-23 04:38:08 UTC
Created attachment 7469 [details]
Screenshot showing 'one'

Given the following program:

let main argv = 

    let combineTwoTupledStrings (one, two)=
        sprintf "First:%s Second:%s" one two

    printfn "%s" <| combineTwoTupledStrings ("hello", "everyone")

When a break point is placed on on the line: "sprintf "First:%s Second:%s" one two" 

The value 'one' is incorrectly shown as null
The value 'two' is incorrectly shown as Unknown Identifiew
The locals display does not include 'two'.
Comment 1 Dave Thomas 2014-07-23 04:38:52 UTC
Created attachment 7470 [details]
Screen shot showing 'two'
Comment 2 Ram Chandra 2014-07-23 06:02:24 UTC
I have checked this issue and I am getting the same behavior.

Steps I followed:

1. Create a "F# console application on XS".
2. Replace the code of "Program.fs" in file with following code 

let main argv = 

    let combineTwoTupledStrings (one, two)=
        sprintf "First:%s Second:%s" one two

    printfn "%s" <| combineTwoTupledStrings ("hello", "everyone")

3. Place a breakpoint on following line :
    sprintf "First:%s Second:%s" one two

4.  Debug the application.

When I hover the cursor over the value of 'one', I observed that the suggestion popup display it null and the values of 'two' is incorrectly shown as 'Unknown Identifier'. I have checked the same on 'Local' debug window and I am getting the same behavior.

Screencast: http://www.screencast.com/t/inFTI0GJipX

Environment Info:

Mac OS X 10.9.3
Xamarin Studio: 5.2 (build 384)

Build Information
Release ID: 502000384
Git revision: 09e06441e39ea272ddda63758fd53013157f7e45
Build date: 2014-07-16 11:15:54-04
Xamarin addins: 2d11dd4dad5b35ca83f24d70e965792a47be8291
Comment 3 David Karlaš 2015-01-07 02:23:15 UTC
This is compiler bug not debugger. You can confirm this by compering results in VisualStudio(it's same behaviour).

Problem is that this method in C# looks like this:
public override string Invoke (Tuple<string, string> tupledArg)
  string one = tupledArg.get_Item1 ();
  string two = tupledArg.get_Item2 ();
  FSharpFunc<string, FSharpFunc<string, string>> clo = ExtraTopLevelOperators.PrintFormatToString<FSharpFunc<string, FSharpFunc<string, string>>> (new PrintfFormat<FSharpFunc<string, FSharpFunc<string, string>>, Unit, string, string, Tuple<string, string>> ("First:%s Second:%s"));
  return FSharpFunc<string, string>.InvokeFast<string> (new Program.combineTwoTupledStrings@5-1 (clo), one, two);

And .mdb(or .pdb) method information look like this:
<method token="0x6000007" signature="System.String Program/combineTwoTupledStrings@5::Invoke(System.Tuple`2&lt;System.String,System.String&gt;)">
  <entry il="0x0" row="5" col="9" file_ref="1" />
  <entry name="one" il_index="0" scope_ref="2" />
  <entry name="two" il_index="1" scope_ref="3" />
  <entry index="0" start="0x0" end="0x2d" />
  <entry index="1" start="0x0" end="0x2d" />
  <entry index="2" start="0x7" end="0x2d" />

So when debugger step into this method string one = tupledArg.get_Item1 (); is not called yet and variable "two" is not visible yet because it's part of scope 3 which starts at ILoffset 0x7... So doing few steps results into entering into scope 3 and both variables being set...

What compiler should do is set sequence point to IL 0xE or something like that(so after both variables are set) instead of 0x0...

Pasting also IL output:
.method public strict virtual 
  instance string Invoke (
    class [mscorlib]System.Tuple`2<string, string> tupledArg
  ) cil managed 
  // Method begins at RVA 0x20f0
  // Code size 45 (0x2d)
  .maxstack 7
  .locals init (
    [0] string,
    [1] string,
    [2] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, string>>

  IL_0000: ldarg.1
  IL_0001: call instance !0 class [mscorlib]System.Tuple`2<string, string>::get_Item1()
  IL_0006: stloc.0
  IL_0007: ldarg.1
  IL_0008: call instance !1 class [mscorlib]System.Tuple`2<string, string>::get_Item2()
  IL_000d: stloc.1
  IL_000e: ldstr "First:%s Second:%s"
  IL_0013: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, string>>, class [FSharp.Core]Microsoft.FSharp.Core.Unit, string, string, class [mscorlib]System.Tuple`2<string, string>>ctor(string)
  IL_0018: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, string>>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0, class [FSharp.Core]Microsoft.FSharp.Core.Unit, string, string>)
  IL_001d: stloc.2
  IL_001e: nop
  IL_001f: ldloc.2
  IL_0020: newobj instance void Program/'combineTwoTupledStrings@5-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, string>>)
  IL_0025: ldloc.0
  IL_0026: ldloc.1
  IL_0027: call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, string>::InvokeFast<string>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<!0, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<!1, !!0>>, !0, !1)
  IL_002c: ret
Comment 4 David Karlaš 2015-01-07 02:31:21 UTC
I reported this also on F# compiler issue tracker.
Comment 5 Dave Thomas 2015-01-14 03:34:45 UTC
Mark as resolved upstream as this is a compiler issue.