www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - funny bug with input range interface and toString

reply spir <denis.spir gmail.com> writes:
Hello,


I have a strange bug with an input range interface. Initially, I had a (rat=
her big) struct called Text with loads of working unittests. When adding a =
range interface, noting worked anymore, any test ran into an infinite loop =
(the terminal writes pages of '[') ending with segfault.
After shrinking the bug's scope,I finally found it happens on simple writel=
n(text). Which is rather weird, because my toString does not iterate on tex=
ts properly speaking (instead on a private array field). Thus, i had the id=
ea to force using toString by explicitely calling it and the bug vanished ;=
-) So, here is the situation:

unittest {
    auto text =3D Text("b=C3=A4con");
    writeln(text);          	// --> infinite loop & segfault
    writeln(text.toString());	// OK
}

Indeed, if I remove the range interface, the bug vanishes as well.
You can find a stripped version of the module, with only the minmum to expo=
se the bug, at https://bitbucket.org/denispir/denispir-d/changeset/39200b49=
9fb9#chg-textbug.d. Note that the range interface itself works fine.

So, it seems that, in my case for any reason, introducing an input range le=
ts D shortcut toString (and try to use what instead?). Look like a bug?


denis
-- -- -- -- -- -- --
vit esse estrany =E2=98=A3

spir.wikidot.com
Dec 13 2010
parent reply "Nick Voronin" <elfy.nv gmail.com> writes:
On Mon, 13 Dec 2010 11:24:48 +0300, spir <denis.spir gmail.com> wrote:

 I have a strange bug with an input range interface. Initially, I had a  
 (rather big) struct called Text with loads of working unittests. When  
 adding a range interface, noting worked anymore, any test ran into an  
 infinite loop (the terminal writes pages of '[') ending with segfault.
property Text front () { return Text(this.stacks[this.rangeIndex]); } Um. There is recursion. front() of Text returns Text. formatValue iterates through Range, trying to format every element of it... but goes nowhere because Range.front never yields anything but itself typewise.
 After shrinking the bug's scope,I finally found it happens on simple  
 writeln(text).
Not so simple, with all underlying mess of templates :-D I suppose it's a bug that instantiation of formatValue for Range types there always tries to iterate manually, ignoring existing toString. void formatValue(Writer, T, Char)(Writer w, T val, ref FormatSpec!Char f) if ( ( is(T == struct) || is(T == union) ) && !isInputRange!T) As you can see it even explicitly mention that default formatting for struct (which can use toString) not to be used for Ranges. I think it's wrong.
 https://bitbucket.org/denispir/denispir-d/changeset/39200b4
9fb9#chg-textbug.d.  
 Note that the range interface itself works fine.
btw, I wonder, how do you build it? I ended up with very long command line for dmd, as there was no makefile and jake/rdmd failed to produce anything ether.
 So, it seems that, in my case for any reason, introducing an input range  
 lets D shortcut toString (and try to use what instead?). Look like a bug?
Yup! Still, stack overflow is due to unconventional Range interface. -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Dec 13 2010
parent reply spir <denis.spir gmail.com> writes:
On Mon, 13 Dec 2010 17:37:19 +0300
"Nick Voronin" <elfy.nv gmail.com> wrote:

 On Mon, 13 Dec 2010 11:24:48 +0300, spir <denis.spir gmail.com> wrote:
=20
 I have a strange bug with an input range interface. Initially, I had a =
=20
 (rather big) struct called Text with loads of working unittests. When =
=20
 adding a range interface, noting worked anymore, any test ran into an =
=20
 infinite loop (the terminal writes pages of '[') ending with segfault.
=20 property Text front () { return Text(this.stacks[this.rangeIndex]); } =20 Um. There is recursion. front() of Text returns Text. formatValue iterate=
s =20
 through Range, trying to format every element of it... but goes nowhere =
=20
 because Range.front never yields anything but itself typewise.
Yes, but returning an element of the same type is the write thing here. (Li= ke in dynamic languages where s[i] returns a singleton s).
 After shrinking the bug's scope,I finally found it happens on simple =20
 writeln(text).
=20 Not so simple, with all underlying mess of templates :-D I suppose it's a=
=20
 bug that instantiation of formatValue for Range types there always tries =
=20
 to iterate manually, ignoring existing toString.
=20
 void formatValue(Writer, T, Char)(Writer w, T val,
          ref FormatSpec!Char f)
 if ( ( is(T =3D=3D struct) || is(T =3D=3D union) ) && !isInputRange!T)
=20
 As you can see it even explicitly mention that default formatting for =20
 struct (which can use toString) not to be used for Ranges. I think it's =
=20
 wrong.
You are right. (With some offline help) finally ended up following the same= reasoning and got to the same conclusion. This is clearly a bug (actualy 2= or 3). I'll post about it on D's main mailing list.
 https://bitbucket.org/denispir/denispir-d/changeset/39200b499fb9#chg-te=
xtbug.d. =20
 Note that the range interface itself works fine.
=20 btw, I wonder, how do you build it? I ended up with very long command lin=
e =20
 for dmd, as there was no makefile and jake/rdmd failed to produce anythin=
g =20
 ether.
I use rdmd for quick testing (because it links automagically). compile: dmd -w -c filename.d build: rdmd -w -offilename" -debug -unittest --build-only filename.d
 So, it seems that, in my case for any reason, introducing an input rang=
e =20
 lets D shortcut toString (and try to use what instead?). Look like a bu=
g?
=20
 Yup! Still, stack overflow is due to unconventional Range interface.
Yes. But the formatValue template selection criteria _must_ check this! Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Dec 13 2010
parent "Nick Voronin" <elfy.nv gmail.com> writes:
On Mon, 13 Dec 2010 21:43:33 +0300, spir <denis.spir gmail.com> wrote:

 I use rdmd for quick testing (because it links automagically).
 compile: dmd -w -c filename.d
 build: rdmd -w -offilename" -debug -unittest --build-only filename.d
Thanks. I missed -of option. -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Dec 13 2010