Bug 5787 – Invisible multiple function calls when using .tupleof

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Windows
Creation time
2011-03-27T08:10:00Z
Last change time
2012-04-23T10:40:02Z
Keywords
performance
Assigned to
nobody
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2011-03-27T08:10:09Z
Through profiling I have found a performance problem in my code. I have later reduced the case and created this demo code: import std.typecons: tuple; import std.c.stdio: printf; auto foo() { printf("foo\n"); return tuple(1, 2); } void main() { foreach (x; foo().tupleof) printf("%d\n", x); } Its output, DMD 2.052: foo 1 foo 2 In my code foo() was an expensive computation. In my opinion in this situation foo() needs to be computed only once (or I'd like some other solution to avoid this invisible multiple calls, like some kind of error, etc).
Comment #1 by bearophile_hugs — 2011-03-28T09:49:05Z
Kai Meyer has shown this related program: import std.typecons: tuple; import std.c.stdio: printf; auto foo() { printf("foo\n"); return tuple(1, 2); } void main() { auto f2 = foo().tupleof; } Its output: foo foo So maybe the problem seems isn't caused by the static foreach.
Comment #2 by kennytm — 2011-03-28T12:02:32Z
The problem is in .tupleof, where (expr).tupleof is rewritten to TypeTuple!((expr).field0, (expr).field1, (expr).field2, ...) even if expr have side effect, e.g. ----------- import std.c.stdio : printf; struct S { int x; int y; } void main() { cast(void) (printf("Hi\n"), S(2,3)).tupleof; } // print "Hi" twice. ----------- This should be rewritten as (tmp=expr, TypeTuple!(tmp.field0, ...)). (The ',' here is a comma expression.)
Comment #3 by lovelydear — 2012-04-23T03:26:46Z
With 2.059 Win32 First example gives: PS E:\DigitalMars\dmd2\samples> rdmd bug foo 1 2 Second example: PS E:\DigitalMars\dmd2\samples> rdmd bug foo Third example: PS E:\DigitalMars\dmd2\samples> rdmd bug Hi
Comment #4 by k.hara.pg — 2012-04-23T10:40:02Z
This issue has been already fixed as part of bug 4940.