www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 3835] New: [CTFE] Fragile CTFE

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835

           Summary: [CTFE] Fragile CTFE
           Product: D
           Version: 2.040
          Platform: Other
        OS/Version: Windows
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: bearophile_hugs eml.cc



This code (that uses CTFE to do something that can be useful, it initializes an
array with values compiled at compile time) compiles and works correctly, but I
think it's too much fragile: if you change the for loop a little, or other
details in genFactorials(), the program stops compiling:

int factorial(int n) {
    if (n == 0)
       return 1;
    return n * factorial(n - 1);
}

int[] genFactorials(int n) {
    int[] result;
    for (; n >= 0; --n)
        result = factorial(n) ~ result;
    return result;
}

const int N = 13;
static const auto factorials = cast(int[N])genFactorials(N - 1);
void main() {}


If you need them, I can show many variants of this program that don't
compile/work.
I think to be useful in real programs CTFE has to be less fragile than this.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 18 2010
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835


Don <clugdbug yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |clugdbug yahoo.com.au




 This code (that uses CTFE to do something that can be useful, it initializes an
 array with values compiled at compile time) compiles and works correctly, but I
 think it's too much fragile: if you change the for loop a little, or other
 details in genFactorials(), the program stops compiling:
Please put in an example that it wouldn't compile! -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 18 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835




 Please put in an example that it wouldn't compile!
OK. This two versions of genFactorials print the wrong results: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 import std.stdio: writeln; int factorial(int n) { if (n == 0) return 1; return n * factorial(n - 1); } int[] genFactorialsA(int n) { int[] result = new int[n + 1]; foreach (i, ref el; result) el = factorial(i); return result; } int[N] genFactorialsB(int N)() { int[N] result; foreach (i, ref el; result) el = factorial(i); return result; } enum int N = 13; static enum auto factorials1 = cast(int[N])genFactorialsA(N - 1); enum auto factorials2 = genFactorialsB!13; void main() { writeln(factorials1); writeln(factorials2); } This version doesn't compile, the compiler raises: test7b.d(7): Error: pure function 'factorial' cannot call impure function 'factorial' test7b.d(12): Error: pure function 'genFactorials' cannot call impure function 'factorial' test7b.d(17): Error: cannot evaluate genFactorials(12) at compile time test7b.d(17): Error: cannot evaluate genFactorials(12) at compile time import std.stdio: writeln; pure int[] genFactorials(int n) { pure static int factorial(int n) { if (n == 0) return 1; return n * factorial(n - 1); } int[] result = new int[n + 1]; foreach (i; 0 .. n+1) result[i] = factorial(i); return result; } enum int N = 13; static enum auto factorials = cast(int[N])genFactorials(N - 1); void main() { writeln(factorials); } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 19 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835


Serg Kovrov <kovrov+puremagic gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |kovrov+puremagic gmail.com



15:09:52 PST ---
Looks like foreach do not work in CTFE. Here is example with two equivalent
functions, one uses 'for', other 'foreach' loops:


 uint[256] crc32_table_for()
 {
     uint[256] table;
     for (uint i = 0; i < 256; ++i) {
         uint crc = i;
         for (int j = 0; j < 8; j++)
             crc = crc & 1 ? (crc >> 1) ^ 0xEDB88320 : crc >> 1;
         table[i] = crc;
     }
     return table;
 }

 uint[256] crc32_table_foreach()
 {
     uint[256] table;
     foreach (n, ref i; table) {
         uint crc = n;
         foreach (j; 0 .. 8)
             crc = crc & 1 ? (crc >> 1) ^ 0xEDB88320 : crc >> 1;
         i = crc;
     }
     return table;
 }

 immutable crc32_table1 = crc32_table_for();
 immutable crc32_table2 = crc32_table_foreach();

 import std.stdio;
 void main()
 {
     writefln("%s", crc32_table1);
     writefln("%s", crc32_table2);
     assert (crc32_table1 == crc32_table2);
 }

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 01 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835




I think foreach(x; items) works in CTFE, but foreach(ref x; items) doesn't work
well.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 01 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835




The first two cases are already present in bug 2411. I don't know about the
third.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 07 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835




I created bug 3912 for the third bug mentioned in the comments, which has
nothing to do with CTFE. Maybe this bug can now be marked as a duplicate of bug
2411?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 09 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835




You can mark this as duplicate. But when an improvement is created, it's
necessary to try it with *all* duplicated examples too, because you must be
sure they are really problems with the same cause.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 09 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835


Don <clugdbug yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |rejects-valid
            Summary|[CTFE] Fragile CTFE         |ref foreach does not work
                   |                            |in CTFE



Bug 2411 is NOT the same as this. (2411 does not involve CTFE). Changing title.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 10 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835




In dmd 2.043 my second tests cases works:

import std.stdio: writeln;

pure int[] genFactorials(int n) {
    pure static int factorial(int n) {
        if (n == 0)
           return 1;
        return n * factorial(n - 1);
    }

    int[] result = new int[n + 1];
    foreach (i; 0 .. n+1)
        result[i] = factorial(i);
    return result;
}

enum int N = 13;
static enum auto factorials = cast(int[N])genFactorials(N - 1);
void main() {
    writeln(factorials);
}


The first test case doesn't work yet.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 10 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835




A reduced test case:

int foo() {
    int[1] arr;
    foreach (ref el; arr)
        el = 10;
    return arr[0];
}
enum int r = foo();
void main() {
    assert(r == 10);
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 10 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835


klickverbot <code klickverbot.at> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |code klickverbot.at



---
This bug is worse than it might seem from reading the »rejects-valid« keyword
–
DMD 2.051 happily executes ref foreach during compile-time, but generates wrong
results silently.

Should we add a »wrong-ctfe« tag or something like that?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 06 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835


Don <clugdbug yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |wrong-code




 This bug is worse than it might seem from reading the »rejects-valid«
keyword –
 DMD 2.051 happily executes ref foreach during compile-time, but generates wrong
 results silently.
 
 Should we add a »wrong-ctfe« tag or something like that?
No, incorrect CTFE should just be marked as wrong-code. Yup, this one's important. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 07 2011
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3835


Don <clugdbug yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |FIXED



Fixed.

D2:
https://github.com/D-Programming-Language/dmd/commit/0219a5f0dcc88076759a4c472582954d0fb804b0

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 08 2011