Thread overview
String switch is odd using betterC
Feb 26, 2020
Abby
Feb 26, 2020
Abby
Feb 26, 2020
Abby
Feb 26, 2020
Simen Kjærås
February 26, 2020
I have a simple enum of strings like so:

enum Alphabet : string
{
    a = "A",
    b = "B",
    c = "C",
    d = "D",
    e = "E",
    f = "F",
    g = "G"
}

and then simple final switch like so:

extern(C) void main()
{
    auto s = Alphabet.f;
    final switch(s)
    {
        case Alphabet.a: break;
        case Alphabet.b: break;
        case Alphabet.c: break;
        case Alphabet.d: break;
        case Alphabet.e: break;
        case Alphabet.f: break;
        case Alphabet.g: break;
    }
}

The problem I have is that this causes:

/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(2999): Error: TypeInfo cannot be used with -betterC

Odd think is that wehen I remove g from my enum it compiles just fine, so it seems that this compilation error occurs only when my enum has more then 6 members.

Any idea why?
February 26, 2020
On Wednesday, 26 February 2020 at 08:25:00 UTC, Abby wrote:
> /dlang/dmd/linux/bin64/../../src/druntime/import/object.d(2999): Error: TypeInfo cannot be used with -betterC
>
> Odd think is that wehen I remove g from my enum it compiles just fine, so it seems that this compilation error occurs only when my enum has more then 6 members.
>
> Any idea why?

Ok so this is enough to reproduce the problem

extern(C) void main()
{
    auto s = "F";
    final switch(s)
    {
        case "A": break;
        case "B": break;
        case "C": break;
        case "D": break;
        case "E": break;
        case "F": break;
        case "G": break;
    }
}
February 26, 2020
On Wednesday, 26 February 2020 at 08:25:00 UTC, Abby wrote:
> Any idea why?

Ok so this is enough to produce the same result, it seems that there is a problem in string switch when there is more the 6 cases.

extern(C) void main()
{
    auto s = "F";
    final switch(s)
    {
        case "A": break;
        case "B": break;
        case "C": break;
        case "D": break;
        case "E": break;
        case "F": break;
        case "G": break;
    }
}
February 26, 2020
On Wednesday, 26 February 2020 at 08:32:50 UTC, Abby wrote:
> On Wednesday, 26 February 2020 at 08:25:00 UTC, Abby wrote:
>> Any idea why?
>
> Ok so this is enough to produce the same result, it seems that there is a problem in string switch when there is more the 6 cases.
>
> extern(C) void main()
> {
>     auto s = "F";
>     final switch(s)
>     {
>         case "A": break;
>         case "B": break;
>         case "C": break;
>         case "D": break;
>         case "E": break;
>         case "F": break;
>         case "G": break;
>     }
> }

This looks like a possible cause:
https://github.com/dlang/druntime/blob/e018a72084e54ecc7466e97c96e4557b96b7f905/src/core/internal/switch_.d#L34

February 26, 2020
On Wednesday, 26 February 2020 at 08:32:50 UTC, Abby wrote:
> On Wednesday, 26 February 2020 at 08:25:00 UTC, Abby wrote:
>> Any idea why?
>
> Ok so this is enough to produce the same result, it seems that there is a problem in string switch when there is more the 6 cases.
>
> extern(C) void main()
> {
>     auto s = "F";
>     final switch(s)
>     {
>         case "A": break;
>         case "B": break;
>         case "C": break;
>         case "D": break;
>         case "E": break;
>         case "F": break;
>         case "G": break;
>     }
> }

The explanation can be found in druntime/import/core/internal/switch_.d: the __switch template does a simple binary search for less than 7 cases, but calls .idup on each case label for >= 7 cases.

There's a comment there about why it's being done, but it seems to be a far more complicated fix than necessary - static immutable cases = [caseLabels]; works just as well, it seems.

Anyway, the current code was added in this commit: https://github.com/dlang/druntime/commit/fa665f6618af7dbc09ed5ba1333f385017b7ece8.

Anyways, reported here: https://issues.dlang.org/show_bug.cgi?id=20613

--
  Simen