www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Unexpected issue with std.format

reply Saurabh Das <saurabh.das gmail.com> writes:
I faced this issue while working with custom formatting for a 
struct. I have reduced the error down to this test program:

import std.format, std.stdio, std.array;

struct Test1
{
     void toString(W, C)(ref W w, scope const ref FormatSpec!C fmt)
     {
         pragma(msg, "Test1 function compiled with W=" ~ 
W.stringof);
         // formatValue(w, this, fmt);
     }
}

struct Test2
{
     void toString(W, C)(ref W w, scope const ref FormatSpec!C fmt)
     {
         pragma(msg, "Test2 function compiled with W=" ~ 
W.stringof);
         formatValue(w, this, fmt);
     }
}

void main()
{
     Test1 t1;
     Test2 t2;

     Appender!string writer;
     auto ff = singleSpec("%s");

     formatValue(writer, t1, ff);
     formatValue(writer, t2, ff);
}

When compiled, the output is:

Test1 function compiled with W=S
Test1 function compiled with W=Appender!string
Test2 function compiled with W=S

1. Why was Test2 never compiled with W=Appender!string?
2. What is "S"?

Essentially, my custom struct was not being formatted using the 
toString method that I had written. Reducing the issue, it seems 
like a call to formatValue with the same type caused the issue. 
If someone can explain what I am doing wrong here, it would 
really help a lot.

Thanks,
Saurabh
Feb 01 2020
next sibling parent Saurabh Das <saurabh.das gmail.com> writes:
On Saturday, 1 February 2020 at 13:39:34 UTC, Saurabh Das wrote:
 I faced this issue while working with custom formatting for a 
 struct. I have reduced the error down to this test program:

 [...]
PS: Currently using DMD64 D Compiler v2.090.0
Feb 01 2020
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/1/20 8:39 AM, Saurabh Das wrote:
 I faced this issue while working with custom formatting for a struct. I 
 have reduced the error down to this test program:
 
 import std.format, std.stdio, std.array;
 
 struct Test1
 {
      void toString(W, C)(ref W w, scope const ref FormatSpec!C fmt)
      {
          pragma(msg, "Test1 function compiled with W=" ~ W.stringof);
          // formatValue(w, this, fmt);
      }
 }
 
 struct Test2
 {
      void toString(W, C)(ref W w, scope const ref FormatSpec!C fmt)
      {
          pragma(msg, "Test2 function compiled with W=" ~ W.stringof);
          formatValue(w, this, fmt);
      }
 }
 
 void main()
 {
      Test1 t1;
      Test2 t2;
 
      Appender!string writer;
      auto ff = singleSpec("%s");
 
      formatValue(writer, t1, ff);
      formatValue(writer, t2, ff);
 }
 
 When compiled, the output is:
 
 Test1 function compiled with W=S
 Test1 function compiled with W=Appender!string
 Test2 function compiled with W=S
 
 1. Why was Test2 never compiled with W=Appender!string?
 2. What is "S"?
 
 Essentially, my custom struct was not being formatted using the toString 
 method that I had written. Reducing the issue, it seems like a call to 
 formatValue with the same type caused the issue. If someone can explain 
 what I am doing wrong here, it would really help a lot.
 
 Thanks,
 Saurabh
 
Something very weird is happening. I switched to fullyQualifiedName!W, and I get *no output*. The "S" comes from hasToString here:https://github.com/dlang/phobos/blob/9fe5cd354f0166b11d32a5c1214932757d8e7eba/std/format.d#L3876-L3899 I tried copying the implementation to a local file, and as expected, I get customPutWriterFormatSpec for both types. But it's only calling one of them in the implementation. I think the only true way to diagnose this is to instrument std.format and see what it's doing with more pragma(msg) calls. Don't have the time right now. -Steve
Feb 01 2020
parent Saurabh Das <saurabh.das gmail.com> writes:
On Saturday, 1 February 2020 at 15:16:41 UTC, Steven 
Schveighoffer wrote:
 On 2/1/20 8:39 AM, Saurabh Das wrote:
 I faced this issue while working with custom formatting for a 
 struct. I have reduced the error down to this test program:
 
 import std.format, std.stdio, std.array;
 
 struct Test1
 {
      void toString(W, C)(ref W w, scope const ref FormatSpec!C 
 fmt)
      {
          pragma(msg, "Test1 function compiled with W=" ~ 
 W.stringof);
          // formatValue(w, this, fmt);
      }
 }
 
 struct Test2
 {
      void toString(W, C)(ref W w, scope const ref FormatSpec!C 
 fmt)
      {
          pragma(msg, "Test2 function compiled with W=" ~ 
 W.stringof);
          formatValue(w, this, fmt);
      }
 }
 
 void main()
 {
      Test1 t1;
      Test2 t2;
 
      Appender!string writer;
      auto ff = singleSpec("%s");
 
      formatValue(writer, t1, ff);
      formatValue(writer, t2, ff);
 }
 
 When compiled, the output is:
 
 Test1 function compiled with W=S
 Test1 function compiled with W=Appender!string
 Test2 function compiled with W=S
 
 1. Why was Test2 never compiled with W=Appender!string?
 2. What is "S"?
 
 Essentially, my custom struct was not being formatted using 
 the toString method that I had written. Reducing the issue, it 
 seems like a call to formatValue with the same type caused the 
 issue. If someone can explain what I am doing wrong here, it 
 would really help a lot.
 
 Thanks,
 Saurabh
 
Something very weird is happening. I switched to fullyQualifiedName!W, and I get *no output*. The "S" comes from hasToString here:https://github.com/dlang/phobos/blob/9fe5cd354f0166b11d32a5c1214932757d8e7eba/std/format.d#L3876-L3899 I tried copying the implementation to a local file, and as expected, I get customPutWriterFormatSpec for both types. But it's only calling one of them in the implementation. I think the only true way to diagnose this is to instrument std.format and see what it's doing with more pragma(msg) calls. Don't have the time right now. -Steve
Thanks for the lead. To exemplify Steve's observation: import std.format, std.stdio, std.array, std.range; struct Test3 { void toString(W, C)(ref W w, scope const ref FormatSpec!C fmt) { import std.traits; pragma(msg, "A: Test2 function compiled with W=" ~ fullyQualifiedName!W.stringof); pragma(msg, "B: Test2 function compiled with W=" ~ W.stringof); } } void main() { Test3 t3; Appender!string writer; auto ff = singleSpec("%s"); formatValue(writer, t3, ff); } Gives an output during compilation: B: Test2 function compiled with W=S Saurabh
Feb 01 2020