Thread overview
[Issue 21044] [CTFE] Infinite loop in ForStatement::interpret
Jul 13, 2020
Iain Buclaw
Jul 13, 2020
Bruce Carneal
Sep 03, 2020
Iain Buclaw
Dec 17, 2022
Iain Buclaw
July 13, 2020
https://issues.dlang.org/show_bug.cgi?id=21044

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ibuclaw@gdcproject.org

--- Comment #1 from Iain Buclaw <ibuclaw@gdcproject.org> ---
Reduction is indeed close to what I anticipated.

---
@property empty(T)(T a)
{
    return !a;
}

auto cmp(R1, R2)(R1 , R2 r2)
{
    for (;;)
        if (r2.empty) return int();
}

auto caseEnclose()
{
    unicode.LC;
}

struct unicode
{
    auto opDispatch(string name)()     {
        static if (cmp(name, ""))
            return ;
    }
}
---

In the original, there would have been a popFront() call, but I suspect that the body of popFront was removed during reduction.

--
July 13, 2020
https://issues.dlang.org/show_bug.cgi?id=21044

Bruce Carneal <bcarneal11@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bcarneal11@gmail.com

--- Comment #2 from Bruce Carneal <bcarneal11@gmail.com> ---
(In reply to Iain Buclaw from comment #0)
> Found on one iteration of mechanically reduced code (still dozens of files, thousands of lines of code). Will copy it and reduce it further, but I suspect that the final product will be code that looks like:
> 
> ---
> int foo()
> {
>     for (;;) { }
>     return 0;
> }
> 
> static assert(foo() == 0);
> ---
> 
> If that is the case, then the compiler really should have proper detection for this, to bail and error out if it finds a loop that never exits during CTFE.

As you noted during beerconf, dlang is Turing complete at compile time, which leaves us with the halting problem. (yes, indeed, we're working with power tools)

Per Stefan's comments at beerconf the current approach to this includes a limit on recursion at compile time.  From your experience, and anticipating recursion rewrites to iterative forms in the future, something more is needed.

Is there some notion of "progress" at compile time that is readily available? A count of the source level symbols resolved perhaps?  There's no "solving" the halting problem of course, just looking for a practical bound.

Seems like current CTFE practice and implementation generate a number of intermediate structures that ultimately collapse to something roughly the size of the source input.

--
September 03, 2020
https://issues.dlang.org/show_bug.cgi?id=21044

--- Comment #3 from Iain Buclaw <ibuclaw@gdcproject.org> ---
(In reply to Bruce Carneal from comment #2)
> (In reply to Iain Buclaw from comment #0)
> > Found on one iteration of mechanically reduced code (still dozens of files, thousands of lines of code). Will copy it and reduce it further, but I suspect that the final product will be code that looks like:
> > 
> > ---
> > int foo()
> > {
> >     for (;;) { }
> >     return 0;
> > }
> > 
> > static assert(foo() == 0);
> > ---
> > 
> > If that is the case, then the compiler really should have proper detection for this, to bail and error out if it finds a loop that never exits during CTFE.
> 
> As you noted during beerconf, dlang is Turing complete at compile time, which leaves us with the halting problem. (yes, indeed, we're working with power tools)
> 
> Per Stefan's comments at beerconf the current approach to this includes a limit on recursion at compile time.  From your experience, and anticipating recursion rewrites to iterative forms in the future, something more is needed.
> 
> Is there some notion of "progress" at compile time that is readily available?  A count of the source level symbols resolved perhaps?  There's no "solving" the halting problem of course, just looking for a practical bound.
> 
> Seems like current CTFE practice and implementation generate a number of intermediate structures that ultimately collapse to something roughly the size of the source input.

There's already some rudimentary code flow analysis in place.  I can't imagine it being too expensive to determine the likelihood of a branch returning.  And if the answer is never (infinite loop), then bail and error before executing the code.

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=21044

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P3

--
December 13
https://issues.dlang.org/show_bug.cgi?id=21044

--- Comment #4 from dlangBugzillaToGithub <robert.schadek@posteo.de> ---
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/dmd/issues/19747

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB

--