On Tue, 14 Dec 2010 05:02:41 -0500, spir <denis.s...@gmail.com> wrote:
Hello,
Had a nice time degugging an issue after having added an input range
interface to a (big) struct type. Finally managed to deduce the problem
happens when writing out an element of the struct type. This introduced
an infinite loop ending in segfault. Found it weird because the struct's
toString does not iterate over the type, so there was no reason to use
the range interface.
This is why I guessed toString was not called. And in fact, forcing its
use by explicitely calling .toString() solved the bug! 2 correspondants
(Stephan Mueller & Ivan Melnychuk) helped me by pointing to the various
template-selection criteria of formatValue.
There seems to be a pair of bugs in the set of formatValue templates
constaints, which cause the following problems:
* If a class defines both toString and a range interface, compiler error
(additional bug pointed by Stephan Mueller).
* For structs, the presence of a range interface shortcuts toString.
* If a range outputs elements of the same type, writing (and probably
other features) runs into an infinite loop. This case is unchecked yet.
The following changes may, I guess, solve the first two problems:
(1) structs added (with classes) to the template selecting the use of
toString
(2) the template that selects the use of ranges checks there is no
toString
(3) the special case of using t.stringof for stucts must be selected
only in last resort -- actually, this case may be suppressed and
integrated into the general class/struct case.
This means changing the following formatValue templates (quickly
written, absolutely untested ;-):
// case use toString (or struct .stringof): add structs
void formatValue(Writer, T, Char)(Writer w, T val, ref FormatSpec!Char f)
if (is(T == class) || is(T == struct))
{
// in case of struct, detect whether toString is defined, else use
T.stringof
}
// case use range interface: check no toString available
// also add a test that the range does not output elements of the same
type!!!
void formatValue(Writer, T, Char)(Writer w, T val,
ref FormatSpec!Char f)
if (
isInputRange!T && !isSomeChar!(ElementType!T) ||
! is(typeof(val.toString() == string))
)
{...}
// special case use T.stringof for struct: useless? (else check no
toString)
void formatValue(Writer, T, Char)(Writer w, T val,
ref FormatSpec!Char f)
if (
is(T == struct) && !isInputRange!T &&
! is(typeof(val.toString() == string))
)
{
put(w, T.stringof);
}
Also, (1) the online doc of std.format seems outdated, no constraint for
instance (2) the in-source doc is rather confusing, several comments do
not describe the following code.
Hope this helps,
Denis
-- -- -- -- -- -- --
vit esse estrany ☣
spir.wikidot.com
Having recently run into this without knowing it, vote++. Also, please
file a bug report (or two).