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