Issue 5708 - [CTFE] Incorrect string constant folding with -inline
Summary: [CTFE] Incorrect string constant folding with -inline
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 critical
Assignee: No Owner
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2011-03-05 17:00 UTC by Jonathan M Davis
Modified: 2015-06-09 05:15 UTC (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Jonathan M Davis 2011-03-05 17:00:59 UTC
From Tom on D.Learn (and I've confirmed it on Linux with both -m32 and -m64):

Minimal test case:

import std.stdio;
import std.conv;

int main(string[] args) {
        int[string] t;
        writeln(text(t));
        return 0;
}

Tried:

dmd -O -release -inline -noboundscheck -c -Isrc src\main.d -> ERROR
dmd    -release -inline -noboundscheck -c -Isrc src\main.d -> ERROR
dmd -O          -inline -noboundscheck -c -Isrc src\main.d -> OK
dmd -O -release         -noboundscheck -c -Isrc src\main.d -> OK
dmd -O -release -inline                -c -Isrc src\main.d -> OK

Where ERROR is:

E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): expression 
expected, not 'EOF'
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ']'
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ')' following template argument list
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ']'
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ')' following template argument list
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ']'
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ')' following template argument list
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ']'
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ')' following template argument list
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ']'
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ')' following template argument list
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ']'
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ')' following template argument list
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ']'
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ')' following template argument list
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ']'
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ')' following template argument list
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ']'
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ')' following template argument list
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ']'
E:\d\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(364): found 'EOF' 
when expecting ')' following template argument list
Comment 1 bearophile_hugs 2011-03-05 17:19:25 UTC
Problem confirmed on Windows, DMD 2.052, compiled with:
-inline -release -noboundscheck

A bit reduced code:


import std.conv: to;
void main() {
    int[string] aa;
    to!string(aa);
}
Comment 2 bearophile_hugs 2011-03-05 17:39:42 UTC
More reduction:

import std.conv: to;
void main() {
    int[int] aa;
    foreach (v; aa)
        to!string("");
}
Comment 3 Jonathan M Davis 2011-03-05 17:59:42 UTC
Well, given the error, it involves creating a tuple, which none of the code here is doing directly, so in theory, it should be possible to reduce it to code which creates a tuple, but I don't know how you'd do that in this case. I assume that v in the foreach loop is a tuple of the key and value, and that's probably where the problem is, but I don't use associative arrays all that often, and when I do, I rarely iterate over them, so I'm not sure. Regardless, if you're really trying to reuduce it, in theory, you should be able to reduce it down to the creation of a tuple with a particular set of types.
Comment 4 bearophile_hugs 2011-03-05 18:41:43 UTC
(In reply to comment #3)
> I assume that v in the foreach loop is a tuple of the key and value,

It's just a value, so it's an int.
Comment 5 kennytm 2011-03-06 00:43:01 UTC
It has nothing to do with the AA. Also, -inline alone is actually enough to trigger this bug. This seems to be a problem in string pooling in compile time.


import std.conv;
import std.typecons;

void ik(T,U)(T t, U u) {
    Tuple!(T,U) x;
}
pragma(msg, ik!(string,string));

void main() {
    () { to!string("lit"); } ();
}
Comment 6 kennytm 2011-03-06 00:53:53 UTC
Further removing the Tuple:



import std.conv;

void ik(T)(T) {
    enum a = to!string("foo") ~ to!string("bar");
    static assert(a == "foobar");
}
alias ik!int ik2;

void main() {
    cast(void) () { to!string("lit"); };
}

As of 2.052 it asserts:

~/Downloads:911$ dmd -inline y.d
y.d(5): Error: static assert  ("foofoo" == "foobar") is false
y.d(7):        instantiated from here: ik!(int)
Comment 7 kennytm 2011-03-06 01:02:07 UTC
Further removing all Phobos dependency:



string b(string s) { return s; }
string a(string s) { return b(s); }

void ik(T)(T) {
    enum p = a("foo");
    enum q = a("bar");
    static assert(q == "bar");
}
alias ik!int ik2;

void main() {
    cast(void) () { a("lit"); };
}



Currently asserts:

y.d(7): Error: static assert  ("foo" == "bar") is false
y.d(9):        instantiated from here: ik!(int)
Comment 8 Nick Sabalausky 2011-04-08 03:33:16 UTC
Don's still-in-progress CTFE overhaul seems to fix this:
https://github.com/donc/dmd/tree/ctfemem
Comment 9 Don 2011-04-08 21:22:35 UTC
(In reply to comment #8)
> Don's still-in-progress CTFE overhaul seems to fix this:
> https://github.com/donc/dmd/tree/ctfemem

Yes, it fixes almost all CTFE bugs involving arrays.

Fixed.
D1:
https://github.com/D-Programming-Language/dmd/commit/ef2a0f1da10331c4de102ca3e029ea1c1c1a46bf

D2:
https://github.com/D-Programming-Language/dmd/commit/0219a5f0dcc88076759a4c472582954d0fb804b0
Comment 10 Jimmy Cao 2011-05-29 19:02:16 UTC
It doesn't seem like this is fixed in dmd 2.053, but it should be according to the changelog.
Comment 11 Don 2011-05-29 21:19:24 UTC
(In reply to comment #10)
> It doesn't seem like this is fixed in dmd 2.053, but it should be according to
> the changelog.

Can you describe what's failing? The test in comment 7 works for me.
Comment 12 Jimmy Cao 2011-05-29 21:31:41 UTC
The test in comment 7 asserts for me.
I'm using dmd 2.053 on Windows.
Comment 13 Jimmy Cao 2011-05-29 22:32:24 UTC
It doesn't work on Fedora 15 either.

I'm using dmd 2.053 directly from the zip file on the digitalmars site (for both Fedora 15 and Windows).

Don, is your dmd built from source?  Maybe there's a difference between mine and yours.
Comment 14 Don 2011-05-30 07:54:25 UTC
I think there was something wrong with that test case, it wasn't instantiating the template. Here's a reduced test case:

string b(string s) { return s; }
string a(string s) { return b(s); }

void bug5708() {
    void m() { a("lit"); }
    static assert(a("foo") == "foo");
    static assert(a("bar") == "bar");
}
Comment 15 Don 2011-06-26 14:56:40 UTC
It was accidentally fixed in this commit:
6072 - [CTFE] Regression(git master): Cannot declare variable inside an 'if' condition

which actually fixed the treatment of comma expressions in CTFE.

https://github.com/D-Programming-Language/dmd/commit/1bcae90e09f5eb6988fcd6df4309a137c9901084

I'm adding this to the test suite so it stays fixed.