Bug 17420 – std.format.formatObject doesn't work with @safe toString specialization
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2017-05-23T17:16:35Z
Last change time
2018-02-16T18:52:17Z
Assigned to
No Owner
Creator
Jack Stouffer
Comments
Comment #0 by jack — 2017-05-23T17:16:35Z
In order to speed up formatting, std.format allows for the following overloads of toString to be defined
const void toString(scope void delegate(const(char)[]) sink, FormatSpec fmt);
const void toString(scope void delegate(const(char)[]) sink, string fmt);
const void toString(scope void delegate(const(char)[]) sink);
This allows std format to skip an allocation because the output string of the object/struct is written directly to the writer.
The problem is that formatObject doesn't work with any of the common function attributes `pure @safe @nogc nothrow`. If the toString overload is marked with any of these, hasToString!(YourType) == 0 or it skips your overload and uses the allocating version.
Either
1. hasToString needs to be modified to recognize these overloads if it's possible to make the existing format code call safe code
2. Failing that, a couple of new specializations of toString should be defined that is more idiomatic of Phobos that gives the function an OutputRange directly, like so
const void toString(O)(O sink, FormatSpec fmt) if (isOutputRange!(O, char));
const void toString(O)(O sink, string fmt) if (isOutputRange!(O, char));
const void toString(O)(O sink) if (isOutputRange!(O, char));
Sorry, yes (didn't have the source code to hand).
> If the toString overload is marked with any of these, hasToString!(YourType) == 0
class N
{
@nogc void toString(scope void delegate(const(char)[])@nogc sink);
}
hasToString!(N, char) is 2. I think the problem is:
class E : Throwable
{
override void toString(scope void delegate(const(char[]))@nogc sink) const;
}
Error: function E.toString does not override any function, did you mean to override 'object.Throwable.toString'?
First, note that Throwable.toString takes a delegate with a const(char[]) parameter, not const(char)[], this is confusing and should be fixed.
Next, if you remove @nogc from sink above it compiles. Shouldn't dmd allow overriding a method that takes a non-@nogc delegate with one that takes a @nogc delegate?