Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] cppfront generates illegal code in an inspect returning a struct #1346

Open
threeifbyair opened this issue Dec 7, 2024 · 2 comments
Open
Labels
bug Something isn't working

Comments

@threeifbyair
Copy link

If I declare a struct, and then use it as the result of an inspect, cppfront generates code constructing the struct with no arguments -- and there's no way to declare an operator= with no arguments in a struct!

Steps to reproduce the behavior:

https://cpp2.godbolt.org/z/K6f9h9qjx

action: @struct type = {
    dx: int;
    dy: int;
}

testfn: (x: int, y: int) -> action = {
    return inspect (x,y) -> action {
        is (0, 0) = action(1, 0);
        is (0, 1) = action(0, 1);
        is _      = action(1, 1);
    };
}

cppfront generates this as the definition of action:

class action {
    public: int dx; 
    public: int dy; 
    public: action(auto&& dx_, auto&& dy_)
CPP2_REQUIRES_ (std::is_convertible_v<CPP2_TYPEOF(dx_), std::add_const_t<int>&> && std::is_convertible_v<CPP2_TYPEOF(dy_), std::add_const_t<int>&>) ;

};

and this as the definition of testfn:

[[nodiscard]] auto testfn(cpp2::impl::in<int> x, cpp2::impl::in<int> y) -> action{
    return [&] () -> action { auto&& _expr = (x, y);
        if (cpp2::impl::is(_expr, (0, 0))) { if constexpr( requires{action(1, 0);} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((action(1, 0))),action> ) return action(1, 0); else return action{}; else return action{}; }
        else if (cpp2::impl::is(_expr, 0, 1)) { if constexpr( requires{action(0, 1);} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((action(0, 1))),action> ) return action(0, 1); else return action{}; else return action{}; }
        else return action(1, 1); }
    (); 
}

Obviously action{} is a zero-parameter constructor, and action doesn't have any zero-argument constructors. (And even if I ensure that action{} is on a code path never taken, both gcc 14 and Clang 19 try to compile it and throw an error.)

@threeifbyair threeifbyair added the bug Something isn't working label Dec 7, 2024
@gregmarr
Copy link
Contributor

gregmarr commented Dec 7, 2024

For it to be default constructible, all the members must have default initializers.

However, I'm not sure this should really require it to be default constructible. Need to ponder a bit more.

@gregmarr
Copy link
Contributor

gregmarr commented Dec 7, 2024

There is a syntax error in the generation here:

cpp2

        is (0, 1) = action(0, 1);

cpp1

else if (cpp2::impl::is(_expr, 0, 1))

Missing parens:

else if (cpp2::impl::is(_expr, (0, 1)))

I fixed that and it compiled properly, as all the if constexpr else branches were unused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants