Skip to content

[BUG] Lowered UFCS doesn't SFINAE #497

Closed
@JohelEGP

Description

@JohelEGP

Title: Lowered UFCS doesn't SFINAE.

Description:

Suppose #496 was fixed.
Attempting to check whether a UFCS candidate expression is well-formed
results in a hard error inside the UFCS machinery.

Minimal reproducer (https://cpp2.godbolt.org/z/Pn46vKMej):

#include "cpp2util.h"
template<typename T> [[nodiscard]] auto f()
requires (CPP2_UFCS_0_NONLOCAL(a, T()))
  {
}
struct B { };
static_assert([]<class T>() {
  return !requires { f<T>(); };
}.template operator()<B>());
Commands:
cppfront -clean-cpp1 main.cpp2
clang++17 -std=c++23 -stdlib=libc++ -lc++abi -pedantic-errors -Wall -Wextra -Wconversion -I . main.cpp

Expected result:

The assertion to pass.

Actual result and error:

Output:
build/_cppfront/main.cpp:3:32: error: use of undeclared identifier 'a'
    3 | requires (CPP2_UFCS_0_NONLOCAL(a, T()))
      |                                ^
build/_cppfront/main.cpp:3:11: note: in instantiation of function template specialization 'f()::(anonymous class)::operator()<B>' requested here
    3 | requires (CPP2_UFCS_0_NONLOCAL(a, T()))
      |           ^
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:746:47: note: expanded from macro 'CPP2_UFCS_0_NONLOCAL'
  746 | #define CPP2_UFCS_0_NONLOCAL(FUNCNAME,PARAM1) \
      |                                               ^
build/_cppfront/main.cpp:3:11: note: while substituting template arguments into constraint expression here
    3 | requires (CPP2_UFCS_0_NONLOCAL(a, T()))
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:746:47: note: expanded from macro 'CPP2_UFCS_0_NONLOCAL'
  746 | #define CPP2_UFCS_0_NONLOCAL(FUNCNAME,PARAM1) \
      |                                               ^
  747 | [](auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
      | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  748 |     if constexpr (requires{ CPP2_FORWARD(obj).FUNCNAME(); }) { \
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  749 |         return CPP2_FORWARD(obj).FUNCNAME(); \
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  750 |     } else { \
      |     ~~~~~~~~~~
  751 |         return FUNCNAME(CPP2_FORWARD(obj)); \
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  752 |     } \
      |     ~~~
  753 | }(PARAM1)
      | ~~~~~~~~~
build/_cppfront/main.cpp:8:22: note: while checking constraint satisfaction for template 'f<B>' required here
    8 |   return !requires { f<T>(); };
      |                      ^
build/_cppfront/main.cpp:8:22: note: in instantiation of function template specialization 'f<B>' requested here
build/_cppfront/main.cpp:8:22: note: in instantiation of requirement here
    8 |   return !requires { f<T>(); };
      |                      ^~~~~~
build/_cppfront/main.cpp:9:12: note: in instantiation of function template specialization '(anonymous class)::operator()<B>' requested here
    9 | }.template operator()<B>());
      |            ^
build/_cppfront/main.cpp:3:32: error: no matching function for call to 'a'
    3 | requires (CPP2_UFCS_0_NONLOCAL(a, T()))
      |                                ^
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:751:16: note: expanded from macro 'CPP2_UFCS_0_NONLOCAL'
  751 |         return FUNCNAME(CPP2_FORWARD(obj)); \
      |                ^~~~~~~~
build/_cppfront/main.cpp:3:11: note: in instantiation of function template specialization 'f()::(anonymous class)::operator()<B>' requested here
    3 | requires (CPP2_UFCS_0_NONLOCAL(a, T()))
      |           ^
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:746:47: note: expanded from macro 'CPP2_UFCS_0_NONLOCAL'
  746 | #define CPP2_UFCS_0_NONLOCAL(FUNCNAME,PARAM1) \
      |                                               ^
build/_cppfront/main.cpp:3:11: note: while substituting template arguments into constraint expression here
    3 | requires (CPP2_UFCS_0_NONLOCAL(a, T()))
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:746:47: note: expanded from macro 'CPP2_UFCS_0_NONLOCAL'
  746 | #define CPP2_UFCS_0_NONLOCAL(FUNCNAME,PARAM1) \
      |                                               ^
  747 | [](auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
      | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  748 |     if constexpr (requires{ CPP2_FORWARD(obj).FUNCNAME(); }) { \
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  749 |         return CPP2_FORWARD(obj).FUNCNAME(); \
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  750 |     } else { \
      |     ~~~~~~~~~~
  751 |         return FUNCNAME(CPP2_FORWARD(obj)); \
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  752 |     } \
      |     ~~~
  753 | }(PARAM1)
      | ~~~~~~~~~
build/_cppfront/main.cpp:8:22: note: while checking constraint satisfaction for template 'f<B>' required here
    8 |   return !requires { f<T>(); };
      |                      ^
build/_cppfront/main.cpp:8:22: note: while substituting deduced template arguments into function template 'f' [with T = B]
build/_cppfront/main.cpp:8:22: note: in instantiation of requirement here
    8 |   return !requires { f<T>(); };
      |                      ^~~~~~
build/_cppfront/main.cpp:9:12: note: in instantiation of function template specialization '(anonymous class)::operator()<B>' requested here
    9 | }.template operator()<B>());
      |            ^
2 errors generated.
References:

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions