Unexpected issue with std.format
Saurabh Das
saurabh.das at gmail.com
Sat Feb 1 15:54:49 UTC 2020
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
More information about the Digitalmars-d-learn
mailing list