Bug 14306 – Wrong codegen with -inline for generic lambdas

Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2015-03-18T16:55:00Z
Last change time
2015-06-17T21:02:32Z
Assigned to
nobody
Creator
andrei

Comments

Comment #0 by andrei — 2015-03-18T16:55:19Z
Consider: import std.algorithm, std.range; struct S { int x; int bump() { ++x; return x; } } int[] fun(ref S s) { auto a = iota(100).map!(x => s.bump).array; return a; } void main() { S s; auto a = fun(s); assert(s.x == 100); } If built without -inline, the code works. Adding -inline makes the assertion fail (s.x is 0). Changing the lambda from x => s.bump to (int x) => s.bump makes the code work, so this is an issue with inlining generic lambdas.
Comment #1 by bugzilla — 2015-03-18T18:30:28Z
Appears to be a problem on all platforms.
Comment #2 by bugzilla — 2015-03-18T21:50:14Z
Test case without imports: --------- template map(alias fun) { auto map(Range)(Range r) { return MapResult!(fun, Range)(r); } } struct MapResult(alias fun, Range) { alias R = Range; R _input; this(R input) { _input = input; } @property bool empty() { return _input.empty; } void popFront() { _input.popFront(); } @property auto ref front() { return fun(_input.front); } } auto iota(int end) { static struct Result { int end = 100; int i = 0; @property bool empty() { return i == end; } @property int front() { return i; } void popFront() { ++i; } } return Result(); } void bar(R)(R r) { foreach (x; r) { } } struct S { int x; int bump() { ++x; return x; } } void fun(ref S s) { iota(100).map!(x => s.bump()).bar; // iota(100).map!((int x) => s.bump()).bar; assert(s.x == 100); } void main() { S s; fun(s); }
Comment #3 by bugzilla — 2015-03-20T07:18:09Z
Even more reduced: ------------------ struct MapResult(alias fun) { void front() { fun(1); } } void bar(R)(R r) { foreach (i; 0..100) { r.front(); } } struct S { int x; int bump() { ++x; return x; } } void fun(ref S s) { MapResult!(x => s.bump())().bar; // fails // MapResult!((int x) => s.bump())().bar; // succeeds if (s.x != 100) assert(0); } void main() { S s; fun(s); } ------------- The failure stems from front() getting inlined. Not sure yet what the problem is.
Comment #4 by bugzilla — 2015-03-20T09:48:03Z
Comment #5 by github-bugzilla — 2015-03-20T12:29:07Z
Commits pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/03f71befbf4d08aef3dfd8065504b0c1f1b6d997 fix Issue 14306 - Wrong codegen with -inline for generic lambdas https://github.com/D-Programming-Language/dmd/commit/3cb7bf3cb93d77d4d7aecde0fd471d6c8afba0a7 Merge pull request #4505 from WalterBright/fix14306 fix Issue 14306 - Wrong codegen with -inline for generic lambdas
Comment #6 by github-bugzilla — 2015-03-20T20:44:15Z
Commit pushed to dmd-1.x at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/464a1edfb21c3cb7148500470a16e560bf30e922 fix Issue 14306 - Wrong codegen with -inline for generic lambdas
Comment #7 by github-bugzilla — 2015-06-17T21:02:32Z