Bug 8224 – std.typetuple: foreach loop returns always first element

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
x86
OS
All
Creation time
2012-06-11T13:33:22Z
Last change time
2024-12-13T18:00:27Z
Keywords
bootcamp
Assigned to
No Owner
Creator
bearophile_hugs
Depends on
12103
Moved to GitHub: dmd#18448 →

Comments

Comment #0 by bearophile_hugs — 2012-06-11T13:33:22Z
import std.stdio: writefln; import std.math: sin, asin, cos, acos, cbrt, pow; import std.functional: compose; import std.typetuple: TypeTuple; void main() { const sin = (in real x) => sin(x); const asin = (in real x) => asin(x); const cos = (in real x) => cos(x); const acos = (in real x) => acos(x); const cube = (in real x) => x ^^ 3; const cbrt = (in real x) => cbrt(x); alias TypeTuple!(sin, cos, cube) dir; alias TypeTuple!(asin, acos, cbrt) inv; foreach (i, f; dir) writefln("%6.3f", compose!(f, inv[i])(0.5)); } Output, dmd 2.060alpha: 0.500 0.866 0.713 Expected output similar to: 0.500 0.500 0.500 Including the source code of std.functional.compose and simplifying it, it shows the problem still: import std.functional: unaryFun; template compose2(fun...) { alias unaryFun!(fun[0]) fun0; alias unaryFun!(fun[1]) fun1; auto compose2(T)(T a) { return fun0(fun1(a)); } } void main() { import std.stdio, std.math, std.typetuple; const sin = (in real x) => sin(x); const asin = (in real x) => asin(x); const cos = (in real x) => cos(x); const acos = (in real x) => acos(x); const cube = (in real x) => x ^^ 3; const cbrt = (in real x) => cbrt(x); alias TypeTuple!(sin, cos, cube) dir; alias TypeTuple!(asin, acos, cbrt) inv; foreach (i, f; dir) writefln("%6.3f", compose2!(f, inv[i])(0.5)); } Output, dmd 2.060alpha: 0.500 0.866 0.713 Removing the unaryFun!() the results become correct: import std.functional: unaryFun; template compose2(fun...) { alias fun[0] fun0; alias fun[1] fun1; auto compose2(T)(T a) { return fun0(fun1(a)); } } void main() { import std.stdio, std.math, std.typetuple; const sin = (in real x) => sin(x); const asin = (in real x) => asin(x); const cos = (in real x) => cos(x); const acos = (in real x) => acos(x); const cube = (in real x) => x ^^ 3; const cbrt = (in real x) => cbrt(x); alias TypeTuple!(sin, cos, cube) dir; alias TypeTuple!(asin, acos, cbrt) inv; foreach (i, f; dir) writefln("%6.3f", compose2!(f, inv[i])(0.5)); } Output, dmd 2.060alpha: 0.500 0.500 0.500
Comment #1 by peter.alexander.au — 2014-02-07T14:43:08Z
Not a problem with unaryFun. I have opened Issue 12103, which reduces this bug.
Comment #2 by bearophile_hugs — 2014-02-07T15:28:32Z
(In reply to comment #1) > Not a problem with unaryFun. I have opened Issue 12103, which reduces this bug. Once Issue 12103 what's left to do for this Issue 8224? Or in other words, why did you open a new issue? :-)
Comment #3 by bearophile_hugs — 2014-02-07T15:29:27Z
(In reply to comment #2) > Once Issue 12103 what's left to do for this Issue 8224? I meant to write: Once Issue 12103 is fixed, what's left to do for this Issue 8224?
Comment #4 by peter.alexander.au — 2014-02-07T15:46:39Z
(In reply to comment #2) > (In reply to comment #1) > > Not a problem with unaryFun. I have opened Issue 12103, which reduces this bug. > > Once Issue 12103 what's left to do for this Issue 8224? Or in other words, why > did you open a new issue? :-) I don't like to drastically change bugs, and the title in this one is misleading for people looking for bugs to solve. Perhaps I should have just changed this one...
Comment #5 by bearophile_hugs — 2014-02-07T16:02:19Z
(In reply to comment #4) > I don't like to drastically change bugs, and the title in this one is > misleading for people looking for bugs to solve. Perhaps I should have just > changed this one... Yes, in such cases the right thing to do is to rename the issue, instead of opening another one :-) So do you want me to close this issue down?
Comment #6 by bugzilla — 2019-12-08T12:43:29Z
Looks like a problem in the TypeTuple foreach-loop. f is always sin.
Comment #7 by simen.kjaras — 2019-12-09T12:16:38Z
The problem is reducible to this: unittest { import std.stdio, std.typetuple; const fun1 = () => 0; const fun2 = () => 1; foreach (i, f; AliasSeq!(fun1, fun2)) { alias f2 = Alias!f; assert(i == f(), "foreach alias works great"); assert(i == f2(), "template is incorrectly cached"); } } As we can see, the issue occurs when f is passed to a template. It seems DMD caches the template instantiation and doesn't update it for each iteration.
Comment #8 by bugzilla — 2019-12-09T12:21:03Z
(In reply to Simen Kjaeraas from comment #7) > It seems DMD caches the template instantiation and doesn't update it for each iteration. Hence, this is a DMD bug and not Phobos?
Comment #9 by simen.kjaras — 2019-12-09T13:44:57Z
Definitely. I didn't even consider the possibility that this could have been filed as a Phobos bug when I commented. :p
Comment #10 by robert.schadek — 2024-12-13T18:00:27Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18448 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB