Bug 5641 – Local instantiation does not save context properly
Status
RESOLVED
Resolution
DUPLICATE
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
All
Creation time
2011-02-22T06:10:00Z
Last change time
2012-11-08T07:57:40Z
Assigned to
nobody
Creator
andrei
Comments
Comment #0 by andrei — 2011-02-22T06:10:45Z
The following program compiles but produces an incorrect result. It prints:
[false, false, false, false, true]
although it should print
[true, true, false, false, false]
When fixing this bug, care must be given to avoiding conservative dynamic allocation of the frames in all cases. This would consistently ruin performance of most of std.algorithm. Instead, the compiler should detect only the cases when context must be saved and only act on those cases. Saving should happen inside non-static struct Result, ideally without dynamic allocation (although I'm not sure how that would be done in the general case).
Alternatively, the compiler could reject the example as written and require the user to save the context manually, in a TBD manner. Don, Walter, let's talk about this, it's important.
After fixing, this example should work if the template map2 is removed and std.algorithm.map is used instead.
import std.algorithm, std.array, std.stdio;
template map2(alias fun)
{
auto map2(R)(R r)
{
struct Result
{
R _input;
this(R input)
{
_input = input;
}
@property bool empty()
{
return !_input.length;
}
void popFront()
{
_input.popFront();
}
@property auto ref front()
{
return fun(_input.front);
}
}
return Result(r);
}
}
auto fun(int[] a)
{
auto y = 42;
auto m = map2!((x) { return x == y; })(a);
return m;
}
void main()
{
auto a = [ 1, 2, 3, 4, 5 ];
auto m = fun(a);
writeln(m);
}
Comment #1 by andrei — 2011-02-22T06:32:25Z
Correction. The program should print "[false, false, false, false, true]". Alternatively, replacing y = 42 with y = 3 should print the originally claimed output.
Comment #2 by wfunction — 2011-02-22T11:46:25Z
Apparently, type-inference also has a problem here:
This code:
int b = 5;
writeln(map!((a) { return a + b; })([0, 1, 2, 3]));
outputs:
[1637916, 1637917, 1637918, 1637919]
if I specify the type of 'a' manually:
int b = 5;
writeln(map!((int a) { return a + b; })([0, 1, 2, 3]));
it outputs:
[0, 1, 2, 3]
Of course, both answers are incorrect, but this might be an indication of another bug; I don't know.
Comment #3 by andrej.mitrovich — 2011-02-22T12:10:35Z
A workaround for those that need this code to work is to use static (it can be used for type inference just like auto):
import std.stdio;
import std.algorithm;
auto fun(int[] a)
{
static y = 3;
return map!((x) { return x == y; })(a);
}
void main()
{
auto a = [ 1, 2, 3, 4, 5 ];
auto m = fun(a);
writeln(m);
}
Comment #4 by verylonglogin.reg — 2012-11-08T07:57:40Z
(In reply to comment #1)
> Correction. The program should print "[false, false, false, false, true]".
> Alternatively, replacing y = 42 with y = 3 should print the originally claimed
> output.
The program from description should print only `false`, after replacing `y = 42` with `y = 3` it should print the only `true` in a middle.
And this is essentially same as Issue 7965 which is fixed so I mark this one as a duplicate.
*** This issue has been marked as a duplicate of issue 7965 ***