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] UFCS fails during constant evaluation only #788

Open
JohelEGP opened this issue Oct 29, 2023 · 3 comments
Open

[BUG] UFCS fails during constant evaluation only #788

JohelEGP opened this issue Oct 29, 2023 · 3 comments
Labels
bug Something isn't working

Comments

@JohelEGP
Copy link
Contributor

Title: UFCS fails during constant evaluation only.

Description:

Given a parameter named after the function being called,
UFCS will fail during constant evaluation only
in the case UFCS would call a member function.

Minimal reproducer (https://cpp2.godbolt.org/z/jKWG4boaq, https://compiler-explorer.com/z/zeqW6MEPK):

t: @struct type = {
  f: (this) -> int == 0;
}

g: (f) = {
  [[assert: t().f() == 0]] // OK.
  static_assert(t().f() == 0); // Error: Argument `f` isn't "`constexpr`".
}

main: () = {
  g(0);
  // g(std::identity()); // Might be OK since P2280R4 (unimplemented).
}
Commands:
cppfront main.cpp2
clang++18 -std=c++23 -stdlib=libc++ -lc++abi -pedantic-errors -Wall -Wextra -Wconversion -Werror=unused-result -I . main.cpp

Expected result: A well-formed program that calls the member function.

Actual result and error:

Cpp2 lowered to Cpp1:
//=== Cpp2 type declarations ====================================================


#include "cpp2util.h"

class t;
  

//=== Cpp2 type definitions and function declarations ===========================

class t {
  public: [[nodiscard]] constexpr auto f() const& -> int;
};

auto g(auto const& f) -> void;
  

auto main() -> int;
  

//=== Cpp2 function definitions =================================================


  [[nodiscard]] constexpr auto t::f() const& -> int { return 0;  }

auto g(auto const& f) -> void{
  cpp2::Default.expects(CPP2_UFCS_0(f, t()) == 0, "");// OK.
  static_assert(CPP2_UFCS_0(f, t()) == 0);// Error: Argument `f` isn't "`constexpr`".
}

auto main() -> int{
  g(0);
  // g(std::identity()); // Might be OK since P2280R4 (unimplemented).
}
Output:
main.cpp2:7:17: error: static assertion expression is not an integral constant expression
    7 |   static_assert(CPP2_UFCS_0(f, t()) == 0);// Error: Argument `f` isn't "`constexpr`".
      |                 ^~~~~~~~~~~~~~~~~~~~~~~~
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:790:38: note: expanded from macro 'CPP2_UFCS_0'
  790 | #define CPP2_UFCS_0(FUNCNAME,PARAM1) \
      |                                      ^
main.cpp2:11:3: note: in instantiation of function template specialization 'g<int>' requested here
   11 |   g(0);
      |   ^
main.cpp2:7:17: note: function parameter 'f' with unknown value cannot be used in a constant expression
    7 |   static_assert(CPP2_UFCS_0(f, t()) == 0);// Error: Argument `f` isn't "`constexpr`".
      |                 ^
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:791:2: note: expanded from macro 'CPP2_UFCS_0'
  791 | [&] CPP2_LAMBDA_NO_DISCARD (auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
      |  ^
main.cpp2:5:20: note: declared here
    5 | auto g(auto const& f) -> void{
      |                    ^
1 error generated.
@JohelEGP JohelEGP added the bug Something isn't working label Oct 29, 2023
@JohelEGP
Copy link
Contributor Author

My reading of https://eel.is/c++draft/expr.const#8
tells me that g(0); will continue failing
whereas g(std::identity()); would be well-formed.

#506's resolution for #550 adds quite some complexity to Cppfront.
The same can be done here to resolve this #788.
The alternative is to just embrace #550 and #788 as limitations of Cppfront,
and require users to not name such variables like the function in a UFCS call.

@JohelEGP
Copy link
Contributor Author

I have potential solutions in mind for this one.
But they also bring complexity to the code of Cppfront.

Maybe trial constant evaluation can be leveraged for a seamless user experience.
An alternative would be to disable UFCS
when in a constant expression (so Cppfront has to know about those)
and f isn't part of the constant expression (determined by lexical name lookup).

@JohelEGP
Copy link
Contributor Author

JohelEGP commented Dec 3, 2023

// g(std::identity()); // Might be OK since P2280R4 (unimplemented).
Yes, it works: https://cpp2.godbolt.org/z/1vrf534qG.

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

1 participant