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));
Comment #1 by nick — 2017-05-24T08:31:13Z
I think you mean formatValue rather than formatObject: https://dlang.org/phobos/std_format.html#.formatValue.10
Comment #2 by jack — 2017-05-24T13:12:28Z
(In reply to Nick Treleaven from comment #1) > I think you mean formatValue rather than formatObject: > > https://dlang.org/phobos/std_format.html#.formatValue.10 No, I meant formatObject https://github.com/dlang/phobos/blob/9a66a6a0647c17d61f551581967abb63aae02545/std/format.d#L3345
Comment #3 by nick — 2017-05-27T13:15:36Z
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?
Comment #4 by nick — 2017-05-27T13:48:19Z
Edit: dmd can't allow it.
Comment #5 by jack — 2018-02-16T18:52:17Z