D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 4423 - [tdpl] enums of struct types
Summary: [tdpl] enums of struct types
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other All
: P2 normal
Assignee: No Owner
URL:
Keywords: rejects-valid, TDPL
Depends on: 6221
Blocks:
  Show dependency treegraph
 
Reported: 2010-07-04 03:23 UTC by Jonathan M Davis
Modified: 2014-08-10 12:54 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 2010-07-04 03:23:53 UTC
I would like to be able to create enums of struct types, but it doesn't seem possible at the moment. You can create manifest constants of a struct using enum, but not an enum with an actual list of values. So, if I were to create a struct that looks like this

struct S
{
    this(string phrase, int num)
    {
        this.phrase = phrase;
        this.num = num;
    }

    int opCmp(const ref S rhs)
    {
        if(phrase < rhs.phrase)
            return -1;
        else if(phrase > rhs.phrase)
            return 1;

        if(num < rhs.num)
            return -1;
        else if(num > rhs.num)
            return 1;

        return 0;
    }

    string phrase;
    int    num;
}


I could create enums like this

enum a = S("hello", 1);
enum b = S("goodbye", 45);


and the compiler is fine with it. However, if I try and create a bona fide enum

enum E : S {a = S("hello", 1),
            b = S("goodbye", 45),
            c = S("world", 22)};


the compiler complains like so

t.d(28): Error: variable __ctmp1 cannot be read at compile time
t.d(28): Error: cannot evaluate __ctmp1.this("hello",1) at compile time
t.d(28): Error: cannot evaluate __ctmp1.this("hello",1) at compile time
t.d(29): Error: cannot evaluate __ctmp2.this("goodbye",45) at compile time
t.d(29): Error: cannot evaluate __ctmp2.this("goodbye",45) at compile time
t.d(28): Error: cast(const(S))__ctmp1.this("hello",1) is not an lvalue
t.d(29): Error: cannot evaluate __ctmp2.this("goodbye",45) at compile time
t.d(29): Error: cannot evaluate __ctmp2.this("goodbye",45).opCmp(cast(const(S))__ctmp1.this("hello",1)) at compile time
t.d(29): Error: Integer constant expression expected instead of __ctmp2.this("goodbye",45).opCmp(cast(const(S))__ctmp1.this("hello",1)) < 0
t.d(28): Error: cast(const(S))__ctmp1.this("hello",1) is not an lvalue
t.d(29): Error: cannot evaluate __ctmp2.this("goodbye",45) at compile time
t.d(29): Error: cannot evaluate __ctmp2.this("goodbye",45).opCmp(cast(const(S))__ctmp1.this("hello",1)) at compile time
t.d(29): Error: Integer constant expression expected instead of __ctmp2.this("goodbye",45).opCmp(cast(const(S))__ctmp1.this("hello",1)) > 0
t.d(30): Error: cannot evaluate __ctmp3.this("world",22) at compile time
t.d(30): Error: cannot evaluate __ctmp3.this("world",22) at compile time
t.d(28): Error: cast(const(S))__ctmp1.this("hello",1) is not an lvalue
t.d(30): Error: cannot evaluate __ctmp3.this("world",22) at compile time
t.d(30): Error: cannot evaluate __ctmp3.this("world",22).opCmp(cast(const(S))__ctmp1.this("hello",1)) at compile time
t.d(30): Error: Integer constant expression expected instead of __ctmp3.this("world",22).opCmp(cast(const(S))__ctmp1.this("hello",1)) < 0
t.d(28): Error: cast(const(S))__ctmp1.this("hello",1) is not an lvalue
t.d(30): Error: cannot evaluate __ctmp3.this("world",22) at compile time
t.d(30): Error: cannot evaluate __ctmp3.this("world",22).opCmp(cast(const(S))__ctmp1.this("hello",1)) at compile time
t.d(30): Error: Integer constant expression expected instead of __ctmp3.this("world",22).opCmp(cast(const(S))__ctmp1.this("hello",1)) > 0


It doesn't look like the CTFE stuff can handle this for some reason. Granted, what CTFE can do is a definite work in progress, but I think that the lack of ability to create an enum of structs is seriously limiting and rather odd given that you can create a manifest constant of a struct using an enum. So, I'd love it if it were possible to create actual enums of a struct type.
Comment 1 Jonathan M Davis 2010-11-28 20:48:56 UTC
I'm elevating this to a bug, since TDPL clearly says that you can have enums of struct types.
Comment 2 Jonathan M Davis 2011-06-19 20:09:48 UTC
Why is this assigned to Andrei of all people? As far as I know, he never does any work on the compiler.
Comment 3 Andrei Alexandrescu 2011-06-20 06:02:50 UTC
Resetting asignee to default.
Comment 4 Don 2011-06-29 01:38:57 UTC
This works in git master, if opCmp has signature
int opCmp(S rhs)            instead of 
int opCmp(const ref S rhs).

The problem lies in enum.c, which tries to determine max and min for the enum by comparing the each element in the enum. Since they are struct literals, they aren't lvalues, so 'const ref' fails.
This is an example of bug 6221.
Comment 5 Andrej Mitrovic 2014-01-06 12:55:14 UTC
The OP sample now works.

Off-topic: Can someone explain to me why Bugzilla keeps logging me out every 10 minutes? Isn't there a way to enable persistent cookies or something? I don't see an option for it in the settings.
Comment 6 hsteoh 2014-08-07 20:40:59 UTC
Works in git HEAD. Full test code:

------
struct S
{
    this(string phrase, int num)
    {   
        this.phrase = phrase;
        this.num = num;
    }
    
    int opCmp(const ref S rhs)
    {   
        if(phrase < rhs.phrase)
            return -1;
        else if(phrase > rhs.phrase)
            return 1;

        if(num < rhs.num)
            return -1;
        else if(num > rhs.num)
            return 1;

        return 0;
    }
    
    string phrase;
    int    num;
}

enum E : S {a = S("hello", 1),
            b = S("goodbye", 45),
            c = S("world", 22)};

void main() {
        import std.stdio;

        E e;
        writeln(e.phrase);

        e = E.b;
        writeln(e.phrase);
}
------

Program output:
------
hello
goodbye
------
Comment 7 github-bugzilla 2014-08-10 12:54:37 UTC
Commit pushed to master at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/3f719e1002b1aaf2c9f2e066f13c97dbd86cc498
fix Issue 4423 - [tdpl] enums of struct types