Bug 11826 – [ctfe] CTFE fails to issue diagnostic for unsupported feature of closures
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
All
Creation time
2013-12-26T09:52:08Z
Last change time
2018-02-10T20:10:16Z
Keywords
CTFE, diagnostic, wrong-code
Assigned to
No Owner
Creator
bearophile_hugs
Comments
Comment #0 by bearophile_hugs — 2013-12-26T09:52:08Z
Compiled with DMD 2.065alpha:
import std.stdio: writeln;
import std.algorithm: cartesianProduct;
auto r = cartesianProduct([1, 2, 3], [10, 20, 30]); // object.Error: Access Violation
void main() {
//auto r = cartesianProduct([1, 2, 3], [10, 20, 30]); // OK
r.writeln;
}
Comment #1 by hsteoh — 2014-08-09T16:25:31Z
This appears to be a bug in std.algorithm.map: here's a minimal test case reduced from the implementation of cartesianProduct:
------
import std.stdio: writeln;
import std.algorithm;
auto f(R1)(R1 range1)
{
return [1].map!(a => range1);
}
auto r = f([1, 2, 3]);
void main() {
r.writeln;
}
------
Moving r inside main() fixes the problem.
Comment #2 by hsteoh — 2014-08-09T17:00:05Z
Managed to reduce it to this near-minimal segfaulting test case:
------
struct MapResult(alias fun, Range)
{
@property front()
{
return fun(0);
}
}
auto f(R1)(R1 range1)
{
return MapResult!(a => range1, int[])();
}
auto r = f([2]);
void main() {
r.front;
}
------
Seems to be a codegen bug; moving the declaration of r inside main() fixes the problem. Disassembly from inside gdb shows a null pointer dereference inside the lambda. Not sure exactly what pointer that is yet, but I suspect it's trying to access the stack frame of f() to get at the parameter 'range1', which has gone out of scope.
Comment #3 by hsteoh — 2014-08-09T17:05:28Z
An even more minimal test case:
------
struct S(alias fun)
{
auto g() { return fun(0); }
}
auto f(int[] arr)
{
return S!(a => arr)();
}
auto r = f([2]);
void main() {
r.g();
}
------
Comment #4 by hsteoh — 2014-08-09T17:12:37Z
Actually, the parameter to f() doesn't have to be an array:
------
struct S(alias fun)
{
auto g() { return fun(0); }
}
auto f(int arr)
{
return S!(a => arr)();
}
auto r = f(2);
void main() {
r.g();
}
------
This seems to prove conclusively that the problem is caused by the lambda trying to access the out-of-scope stack frame of f().
Comment #5 by hsteoh — 2014-08-09T21:09:54Z
As pointed out by Timon Gehr on the forum, this bug seems to be a failure to detect an unsupported feature in CTFE. Moving r=f(2) line into main() and changing it from auto to enum (to force CTFE) triggers the same problem.
Comment #6 by greensunny12 — 2018-02-10T20:10:16Z
2.062 to 2.066.0: Failure with output: --- killed by signal 11
Since 2.067.1: Success with output: [Tuple!(int, int)(1, 10), Tuple!(int, int)(1, 20), Tuple!(int, int)(1, 30), Tuple!(int, int)(2, 10), Tuple!(int, int)(2, 20), Tuple!(int, int)(2, 30), Tuple!(int, int)(3, 10), Tuple!(int, int)(3, 20), Tuple!(int, int)(3, 30)]
https://run.dlang.io/is/Bb5RGA