hsutter / cppfront

A personal experimental C++ Syntax 2 -> Syntax 1 compiler
Other
5.56k stars 248 forks source link

[BUG] Initializing an enum array does not compile #1316

Open MatthieuHernandez opened 1 month ago

MatthieuHernandez commented 1 month ago

I try to compile this simple code:

Color: @enum<u8> type = {
    Black: = 0;
    White: = 1;
}
main: () = {
    colors: std::array<Color, 3> = (Color::Black);
}

The C++ code is generated correctly but I get an error when compiling.

main.cpp2:6:40: error: chosen constructor is explicit in copy-initialization
    6 |     std::array<Color,3> colors {Color::Black}; 
      |                                        ^~~~~
main.cpp2:12:18: note: explicit constructor declared here
   12 | constexpr Color::Color()
      |                  ^
main.cpp2:6:40: note: in implicit initialization of array element 1 with omitted initializer
    6 |     std::array<Color,3> colors {Color::Black}; 
      |                                        ^
1 error generated.

Here is the code I ran: https://cpp2.godbolt.org/z/MnrPqT4fK

gregerolsson commented 1 month ago

I'm wondering if something really breaking has happened lately. I can't even get the hello world example to compile either.

https://cpp2.godbolt.org/z/3n3YW5rdW

JohelEGP commented 1 month ago

Yes. Commit 2c03e416bf3ceb1d2f94f148fc026e4de490b242 happened, which made single-expression functions be not order independent. Add { } around its body, and it compiles again: https://cpp2.godbolt.org/z/j55sP1soo.

MatthieuHernandez commented 1 month ago

@JohelEGP Yes, but what's the solution to my issue? It doesn't seem to be related to my problem.

JohelEGP commented 1 month ago

If you add @print after, you'll see that it has this (https://cpp2.godbolt.org/z/P6TYxEasK):

    operator=:(out this, ) == 
    {
        _value = Black._value;
    }

If you attempt to add an implicit default constructor, e.g. (https://cpp2.godbolt.org/z/hqonP3dbG):

    operator=: (implicit out this) = {
         this = Black;
    }

It'll fail with:

main.cpp2(4,5): error: while applying @enum - in a 'enum' type, the name 'operator=' is reserved for use by the 'enum' implementation

If you want to use @enum with std::array like that, then @enum will need to emit an implicit default constructor, or allow the user to write one.

MatthieuHernandez commented 1 month ago

Yes, cpp2 enum should have a default constructor. I'd like to contribute to the cppfront project but I'm not sure where to start, the code is a little difficult to grasp.

JohelEGP commented 1 month ago

Oh, but it does have a default constructor, it's just explicit. So this works: colors: std::array<Color, 3> = (Color(), Color(), Color()); (https://cpp2.godbolt.org/z/9Wrj8qKd8).

MatthieuHernandez commented 1 month ago

Ah yes indeed, thank you 😊

MatthieuHernandez commented 1 month ago

@JohelEGP In fact, I have the same problem with any objects, if I redefine the constructor. I feel like there's no way to write this or an equivalent:

Color: type = {
    value: i32 = 0;

    operator=:(out this) = {
        value++;
    }
}
main: () = {
    colors: std::array<Color, 1000> = ();
    std::cout << Color[999].value << std::endl;
}

This colors: std::array<Color, 1000> = (); required an implicit constructor on Color that isn't possible for now. And this colors: std::array<Color, 1000>; prodce this error program violates initialization safety guarantee which seems normal.

But my conclusion is that for the moment it's impossible to declare an array of 1000 objects without writing them all one by one. So to keep on progressing on my project I'll have to use std::vector instead of std::array.

Please feel free to correct me if I'm talking nonsense :sweat_smile:

JohelEGP commented 1 month ago

That out this parameter is missing that implicit keyword above.

MatthieuHernandez commented 1 month ago

Oh yes, sorry, I didn't realize that implicit keyword existed in cpp2. I totally missed it when I looked at the documentation. Now everything is working properly, I spent so much time pulling my hair out for nothing :grin: