www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 9541] New: CTFE: wrong code with delegates, recursion

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

           Summary: CTFE: wrong code with delegates, recursion
           Product: D
           Version: unspecified
          Platform: All
        OS/Version: All
            Status: NEW
          Keywords: CTFE, wrong-code
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: nilsbossung googlemail.com


--- Comment #0 from Nils <nilsbossung googlemail.com> 2013-02-19 16:49:00 PST
---
CTFE: wrong code with delegates, recursion

Probably two symptoms of the same cause:

A) infinite loop
---
cat > test_a.d <<code
void main() {
    assert(go() == 1); // passes
    enum e = go(); // infinite loop
}
int go() {
    int result;
    S().into((s) {result = s;});
    return result;
}
struct S {
    void into(void delegate(int) sink) {
        put(sink, R(true));
    }
}
struct R {
    bool set;
    void into(void delegate(int) sink) {
        if(set) put(sink, R(false));
        else sink(1);
    }
}
// a lengthy way to write r.into(sink)
void put(void delegate(int) sink, R r) {
    r.into((s) {sink(s);});
}
code
dmd test_a.d
---
test_a.d(24): Error: delegate test_a.put.__lambda4!(int).__lambda4 CTFE
recursion limit exceeded
test_a.d(24):        called from here: sink(s)
test_a.d(24):        994 recursive calls to function __lambda4
test_a.d(19):        called from here: sink(1)
test_a.d(24):        called from here: r.into(delegate void(int s)
{
sink(s);
}
)
test_a.d(18):        called from here: put(sink, R(false))
test_a.d(24):        called from here: r.into(delegate void(int s)
{
sink(s);
}
)
test_a.d(12):        called from here: put(sink, R(true))
test_a.d(7):        called from here: S().into(delegate void(int s)
{
result = s;
}
)
test_a.d(3):        called from here: go()
---

B) variable of enclosing scope doesn't get set
---
cat > test_b.d <<code
void main() {
    assert(go() == 1); // passes
    enum e = go();
}
int go() {
    int result;
    R(true).into((s) {result = s;});
    return result;
}
struct R {
    bool set;
    void into(void delegate(int) sink) {
        int result = -1;
        if(set) {
            R(false).into((s) {
                result = s;
                assert(result == 1); // passes
            });
            assert(result == 1); // fails in CTFE
            sink(result);
        } else sink(1);
    }
}
code
dmd test_b.d
---
test_b.d(19): Error: assert(result == 1) failed
test_b.d(7):        called from here: R(true).into(delegate void(int s)
{
result = s;
}
)
test_b.d(3):        called from here: go()
---

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



--- Comment #1 from Nils <nilsbossung googlemail.com> 2013-02-20 16:03:31 PST
---
Yup, they both boil down to this:
---
cat > test.d <<code
enum e = (){
    into(null, 42);
    return true;
}();
void into(void delegate() sink, int set) {
    if(set == 42) into(() {assert(set != 13);}, 13);
    else sink();
}
code
dmd -c test.d
---
test.d(6): Error: assert(set != 13) failed
---
(output truncated)

Apparently, the delegate sees the wrong variables.

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



--- Comment #2 from Don <clugdbug yahoo.com.au> 2013-02-27 00:45:20 PST ---
A slight reduction, which removes the delegate literal with a nested function.
==================
bool into(void delegate() sink, int set) {
    void xxx() {
        assert(set != 13);
    }
    if(set == 42)
        into(&xxx, 13);
    else
        sink();
    return true;
}
static assert(into(null, 42));
==================
This may be quite difficult to fix, since it has exposed a design flaw in the
current CTFE implementation.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 27 2013