Thread overview
[Issue 21228] Templated toString silently ignored when it can't be instantiated
[Issue 21228] OutputRange-based toString is silently ignored if isOutputRange is not imported
[Issue 21228] Templated toString silently ignored when it cant be instantiated
Sep 05, 2020
Simen Kjaeraas
Sep 05, 2020
Dlang Bot
Sep 06, 2020
Simen Kjaeraas
Dec 05, 2020
Walter Bright
Dec 17, 2022
Iain Buclaw
September 05, 2020
https://issues.dlang.org/show_bug.cgi?id=21228

moonlightsentinel@disroot.org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |moonlightsentinel@disroot.o
                   |                            |rg
          Component|dmd                         |phobos

--- Comment #1 from moonlightsentinel@disroot.org ---
Nope, this is an issue with the toString detection in phobos. dmd reports an error if the template constraint fails to compile (see https://run.dlang.io/is/9g2V1G).

The problem is that phobos uses speculative compilation to detect if a struct defines toString - which swallows the aforementioned error message.

--
September 05, 2020
https://issues.dlang.org/show_bug.cgi?id=21228

Simen Kjaeraas <simen.kjaras@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |simen.kjaras@gmail.com
            Summary|OutputRange-based toString  |Templated toString silently
                   |is silently ignored if      |ignored when it cant be
                   |isOutputRange is not        |instantiated
                   |imported                    |

--- Comment #2 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
All of the below cases are instances of this same issue:

struct S1 {
    string toString()() {
        nonExistent();
    }
}

struct S2 {
    void toString(R)(ref R r) if (isOutputRange!(R, char)) {}
}

struct S3 {
    import std.range : isOutputRange;
    void toString(R)(ref R r) if (isOutputRange!(R, char)) {
        nonExistent();
    }
}

unittest {
    import std.conv : to;
    assert(S1().to!string == "S1()");
    assert(S2().to!string == "S2()");
    assert(S3().to!string == "S3()");
}

formatValueImpl in std.format already tests for @disabled toString - it should also test for instantiability.

--
September 05, 2020
https://issues.dlang.org/show_bug.cgi?id=21228

Dlang Bot <dlang-bot@dlang.rocks> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull

--- Comment #3 from Dlang Bot <dlang-bot@dlang.rocks> ---
@Biotronic created dlang/phobos pull request #7617 "Fix issue 21228 - Templated toString silently ignored when it cant be…" fixing this issue:

- Fix issue 21228 - Templated toString silently ignored when it cant be instantiated

https://github.com/dlang/phobos/pull/7617

--
September 05, 2020
https://issues.dlang.org/show_bug.cgi?id=21228

Joseph Rushton Wakeling <joseph.wakeling@webdrake.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|Templated toString silently |Templated toString silently
                   |ignored when it cant be     |ignored when it can't be
                   |instantiated                |instantiated

--
September 06, 2020
https://issues.dlang.org/show_bug.cgi?id=21228

--- Comment #4 from Joseph Rushton Wakeling <joseph.wakeling@webdrake.net> ---
One thing I don't understand here: why is the missing symbol not detected _anyway_ regardless of whether any attempt is made to instantiate the template or not?  This feels like a more general problem where bugs in templates remain unflagged by the compiler if the templated code is not used.

It strikes me that if it's possible to address that, it might address the observed problem more robustly than just addressing how phobos consumes the errors.

--
September 06, 2020
https://issues.dlang.org/show_bug.cgi?id=21228

--- Comment #5 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
A missing toString is not an error - struct S {} should print.

One issue is there's umpteen different possible signatures for toString, and we don't know which was intended, so we could just be calling it wrong. Once we've figured out none of the possible ways is correct, we can say for sure that something's wrong, but not exactly what.

We could introduce something like __traits(getErrors, somecode) that would return the resulting error messages from an invocation, but 1) we don't have that, and 2) even if we did, inspecting error messages to figure out what's wrong is error-prone, and the exact text of the error messages may change in the future (at least until issue 10335 is implemented).

Perhaps a better option would be something like __traits(errorLocation, someInstantiation), that would return "body", "arguments", "template arguments", or "template constraints", depending on where the instantiation fails. I'm still not sold on that, though.

--
December 05, 2020
https://issues.dlang.org/show_bug.cgi?id=21228

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla@digitalmars.com

--- Comment #6 from Walter Bright <bugzilla@digitalmars.com> ---
(In reply to Joseph Rushton Wakeling from comment #4)
> The problem is that phobos uses speculative compilation to detect if a struct defines toString - which swallows the aforementioned error message.

What writeln() could do is first speculatively check to see that the symbol toString exists, and if it's there then compile it for keeps, rather than speculatively checking to see if calling it compiles.

That way it won't be silently swallowing the errors in compiling the toString call.

Re-categorizing as a problem in the std.stdio implementation of writeln().

A way to see if a symbol exists is to do something like:

    __traits(compiles, alias xxx = toString);

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=21228

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P3

--
December 01
https://issues.dlang.org/show_bug.cgi?id=21228

--- Comment #7 from dlangBugzillaToGithub <robert.schadek@posteo.de> ---
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/phobos/issues/10438

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB

--