September 05, 2020 [Issue 21228] New: OutputRange-based toString is silently ignored if isOutputRange is not imported | ||||
|---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=21228 Issue ID: 21228 Summary: OutputRange-based toString is silently ignored if isOutputRange is not imported Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: normal Priority: P1 Component: dmd Assignee: nobody@puremagic.com Reporter: joseph.wakeling@webdrake.net The following minimal example shows the problematic behaviour. A struct is defined with a custom toString that follows the recommendations and examples in std.format. However, there is a bug in the code: the `isOutputRange` template check is used but never imported. ``` struct S { int n; void toString (Output) (ref Output output) if (isOutputRange!(Output, char)) { import std.format : formattedWrite; output.formattedWrite!"%s"(2 * this.n); } } void main () { import std.stdio : writeln; auto s = S(2); // should output `4` if output-range toString is used, // but will output `S(2)` if not writeln(s); } ``` This code compiles and runs fine, and produces the default struct formatting output: S(2) ... instead of the custom toString expected output: 4 ... so, the custom toString is being silently ignored. I assume the reason is that the `if (isOutputRange!(Output, char))` check evaluates to false because the `isOutputRange` symbol is not defined, so the toString implementation is never resolved. This is very unintuitive, as one would expect compilation to fail because of the undefined `isOutputRange` symbol. Given that this templated `toString` form is the standard recommendation for how to write custom string formatting, it seems important that user implementation bugs like the one above should be clearly exposed -- not silently elided as described here. -- | ||||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply